Remove direct access to enqueuer through use of WorldImpact

R=het@google.com

Review URL: https://codereview.chromium.org/2527973002 .
This commit is contained in:
Johnni Winther 2016-11-29 09:05:53 +01:00
parent bf13fc1b28
commit c102d3f72a
21 changed files with 914 additions and 739 deletions

View file

@ -82,7 +82,8 @@ abstract class Backend extends Target {
void initializeHelperClasses() {}
void enqueueHelpers(ResolutionEnqueuer world);
/// Compute the [WorldImpact] for backend helper methods.
WorldImpact computeHelpersImpact();
/// Creates an [Enqueuer] for code generation specific to this backend.
Enqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler);
@ -116,21 +117,27 @@ abstract class Backend extends Target {
/// Enable deferred loading. Returns `true` if the backend supports deferred
/// loading.
bool enableDeferredLoadingIfSupported(
ResolutionEnqueuer enqueuer, Spannable node);
bool enableDeferredLoadingIfSupported(Spannable node);
/// Returns the [WorldImpact] of enabling deferred loading.
WorldImpact computeDeferredLoadingImpact() => const WorldImpact();
/// Called during codegen when [constant] has been used.
void computeImpactForCompileTimeConstant(ConstantValue constant,
WorldImpactBuilder impactBuilder, bool isForResolution) {}
/// Called to notify to the backend that a class is being instantiated.
// TODO(johnniwinther): Remove this. It's only called once for each [cls] and
// only with [Compiler.globalDependencies] as [registry].
void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {}
/// Called to notify to the backend that a class is being instantiated. Any
/// backend specific [WorldImpact] of this is returned.
WorldImpact registerInstantiatedClass(ClassElement cls,
{bool forResolution}) =>
const WorldImpact();
/// Called to notify to the backend that a class is implemented by an
/// instantiated class.
void registerImplementedClass(ClassElement cls, Enqueuer enqueuer) {}
/// instantiated class. Any backend specific [WorldImpact] of this is
/// returned.
WorldImpact registerImplementedClass(ClassElement cls,
{bool forResolution}) =>
const WorldImpact();
/// Called to instruct to the backend register [type] as instantiated on
/// [enqueuer].
@ -141,40 +148,47 @@ abstract class Backend extends Target {
void registerTypeVariableBoundsSubtypeCheck(
DartType typeArgument, DartType bound) {}
/**
* Call this to register that an instantiated generic class has a call
* method.
*/
void registerCallMethodWithFreeTypeVariables(
Element callMethod, Enqueuer enqueuer) {}
/// Called to register that an instantiated generic class has a call method.
/// Any backend specific [WorldImpact] of this is returned.
///
/// Note: The [callMethod] is registered even thought it doesn't reference
/// the type variables.
WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod,
{bool forResolution}) =>
const WorldImpact();
/// Called to instruct the backend to register that a closure exists for a
/// function on an instantiated generic class.
void registerClosureWithFreeTypeVariables(
Element closure, Enqueuer enqueuer) {}
/// function on an instantiated generic class. Any backend specific
/// [WorldImpact] of this is returned.
WorldImpact registerClosureWithFreeTypeVariables(Element closure,
{bool forResolution}) =>
const WorldImpact();
/// Call this to register that a member has been closurized.
void registerBoundClosure(Enqueuer enqueuer) {}
/// Called to register that a member has been closurized. Any backend specific
/// [WorldImpact] of this is returned.
WorldImpact registerBoundClosure() => const WorldImpact();
/// Call this to register that a static function has been closurized.
void registerGetOfStaticFunction(Enqueuer enqueuer) {}
/// Called to register that a static function has been closurized. Any backend
/// specific [WorldImpact] of this is returned.
WorldImpact registerGetOfStaticFunction() => const WorldImpact();
/**
* Call this to register that the [:runtimeType:] property has been accessed.
*/
void registerRuntimeType(Enqueuer enqueuer) {}
/// Called to register that the `runtimeType` property has been accessed. Any
/// backend specific [WorldImpact] of this is returned.
WorldImpact registerRuntimeType() => const WorldImpact();
/// Call this to register a `noSuchMethod` implementation.
/// Called to register a `noSuchMethod` implementation.
void registerNoSuchMethod(FunctionElement noSuchMethodElement) {}
/// Call this method to enable support for `noSuchMethod`.
void enableNoSuchMethod(Enqueuer enqueuer) {}
/// Called to enable support for `noSuchMethod`. Any backend specific
/// [WorldImpact] of this is returned.
WorldImpact enableNoSuchMethod() => const WorldImpact();
/// Returns whether or not `noSuchMethod` support has been enabled.
bool get enabledNoSuchMethod => false;
/// Call this method to enable support for isolates.
void enableIsolateSupport(Enqueuer enqueuer) {}
/// Called to enable support for isolates. Any backend specific [WorldImpact]
/// of this is returned.
WorldImpact enableIsolateSupport({bool forResolution});
void registerConstSymbol(String name) {}
@ -206,7 +220,10 @@ abstract class Backend extends Target {
return false;
}
void registerStaticUse(Enqueuer enqueuer, Element element) {}
/// Called to register that [element] is statically known to be used. Any
/// backend specific [WorldImpact] of this is returned.
WorldImpact registerStaticUse(Element element, {bool forResolution}) =>
const WorldImpact();
/// This method is called immediately after the [LibraryElement] [library] has
/// been created.
@ -314,7 +331,9 @@ abstract class Backend extends Target {
void forgetElement(Element element) {}
/// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
WorldImpact computeMainImpact(Enqueuer enqueuer, MethodElement mainMethod) {}
WorldImpact computeMainImpact(MethodElement mainMethod,
{bool forResolution}) =>
const WorldImpact();
/// Returns the location of the patch-file associated with [libraryName]
/// resolved from [plaformConfigUri].

View file

@ -159,6 +159,11 @@ class CodegenRegistry {
String toString() => 'CodegenRegistry for $currentElement';
/// Add the uses in [impact] to the impact of this registry.
void addImpact(WorldImpact impact) {
worldImpact.addImpact(impact);
}
@deprecated
void registerInstantiatedClass(ClassElement element) {
registerInstantiation(element.rawType);

View file

@ -256,8 +256,7 @@ abstract class Compiler implements LibraryLoaderListener {
}
tasks = [
dietParser =
new DietParserTask(idGenerator, backend, reporter, measurer),
dietParser = new DietParserTask(idGenerator, backend, reporter, measurer),
scanner = createScannerTask(),
serialization = new SerializationTask(this),
libraryLoader = new LibraryLoaderTask(
@ -553,9 +552,10 @@ abstract class Compiler implements LibraryLoaderListener {
});
}
void computeMain() {
if (mainApp == null) return;
WorldImpact computeMain() {
if (mainApp == null) return const WorldImpact();
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
Element main = mainApp.findExported(Identifiers.main);
ErroneousElement errorElement = null;
if (main == null) {
@ -596,7 +596,7 @@ abstract class Compiler implements LibraryLoaderListener {
parameter);
mainFunction = backend.helperForMainArity();
// Don't warn about main not being used:
enqueuer.resolution.registerStaticUse(new StaticUse.foreignUse(main));
impactBuilder.registerStaticUse(new StaticUse.foreignUse(main));
});
}
}
@ -613,6 +613,7 @@ abstract class Compiler implements LibraryLoaderListener {
reporter.reportWarningMessage(errorElement, errorElement.messageKind,
errorElement.messageArguments);
}
return impactBuilder;
}
/// Analyze all members of the library in [libraryUri].
@ -640,7 +641,7 @@ abstract class Compiler implements LibraryLoaderListener {
/// Performs the compilation when all libraries have been loaded.
void compileLoadedLibraries() =>
selfTask.measureSubtask("Compiler.compileLoadedLibraries", () {
computeMain();
WorldImpact mainImpact = computeMain();
mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
@ -649,12 +650,13 @@ abstract class Compiler implements LibraryLoaderListener {
// something to the resolution queue. So we cannot wait with
// this until after the resolution queue is processed.
deferredLoadTask.beforeResolution(this);
ImpactStrategy impactStrategy = backend.createImpactStrategy(
impactStrategy = backend.createImpactStrategy(
supportDeferredLoad: deferredLoadTask.isProgramSplit,
supportDumpInfo: options.dumpInfo,
supportSerialization: serialization.supportSerialization);
phase = PHASE_RESOLVING;
enqueuer.resolution.applyImpact(mainImpact);
if (options.resolveOnly) {
libraryLoader.libraries.where((LibraryElement library) {
return !serialization.isDeserialized(library);
@ -678,9 +680,13 @@ abstract class Compiler implements LibraryLoaderListener {
}
}
}
if (deferredLoadTask.isProgramSplit) {
enqueuer.resolution
.applyImpact(backend.computeDeferredLoadingImpact());
}
// Elements required by enqueueHelpers are global dependencies
// that are not pulled in by a particular element.
backend.enqueueHelpers(enqueuer.resolution);
enqueuer.resolution.applyImpact(backend.computeHelpersImpact());
resolveLibraryMetadata();
reporter.log('Resolving...');
if (mainFunction != null && !mainFunction.isMalformed) {
@ -735,7 +741,8 @@ abstract class Compiler implements LibraryLoaderListener {
phase = PHASE_COMPILING;
backend.onCodegenStart();
if (hasIsolateSupport) {
backend.enableIsolateSupport(enqueuer.codegen);
enqueuer.codegen
.applyImpact(backend.enableIsolateSupport(forResolution: false));
}
if (compileAll) {
libraryLoader.libraries.forEach((LibraryElement library) {
@ -842,7 +849,6 @@ abstract class Compiler implements LibraryLoaderListener {
work.element,
() => selfTask.measureSubtask("world.applyImpact", () {
enqueuer.applyImpact(
impactStrategy,
selfTask.measureSubtask(
"work.run", () => work.run(this, enqueuer)),
impactSource: work.element);
@ -853,19 +859,19 @@ abstract class Compiler implements LibraryLoaderListener {
void processQueue(Enqueuer enqueuer, MethodElement mainMethod) {
selfTask.measureSubtask("Compiler.processQueue", () {
enqueuer.applyImpact(
impactStrategy,
enqueuer.nativeEnqueuer
.processNativeClasses(libraryLoader.libraries));
enqueuer.open(impactStrategy);
enqueuer.applyImpact(enqueuer.nativeEnqueuer
.processNativeClasses(libraryLoader.libraries));
if (mainMethod != null && !mainMethod.isMalformed) {
enqueuer.applyImpact(
impactStrategy, backend.computeMainImpact(enqueuer, mainMethod));
enqueuer.applyImpact(backend.computeMainImpact(mainMethod,
forResolution: enqueuer.isResolutionQueue));
}
if (options.verbose) {
progress.reset();
}
emptyQueue(enqueuer);
enqueuer.queueIsClosed = true;
enqueuer.close();
// Notify the impact strategy impacts are no longer needed for this
// enqueuer.
impactStrategy.onImpactUsed(enqueuer.impactUse);

View file

@ -843,8 +843,8 @@ class DeferredLoadTask extends CompilerTask {
});
}
if (isProgramSplit) {
isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported(
compiler.enqueuer.resolution, lastDeferred);
isProgramSplit =
compiler.backend.enableDeferredLoadingIfSupported(lastDeferred);
}
}

View file

@ -79,6 +79,22 @@ abstract class Enqueuer {
WorldBuilder get universe;
native.NativeEnqueuer get nativeEnqueuer;
void forgetElement(Element element, Compiler compiler);
// TODO(johnniwinther): Initialize [_impactStrategy] to `null`.
ImpactStrategy _impactStrategy = const ImpactStrategy();
ImpactStrategy get impactStrategy => _impactStrategy;
void open(ImpactStrategy impactStrategy) {
_impactStrategy = impactStrategy;
}
void close() {
// TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
// to `true` here.
_impactStrategy = const ImpactStrategy();
}
void processInstantiatedClassMembers(ClassElement cls);
void processInstantiatedClassMember(ClassElement cls, Element member);
void handleUnseenSelectorInternal(DynamicUse dynamicUse);
@ -110,8 +126,7 @@ abstract class Enqueuer {
/// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provided
/// the impact strategy will remove it from the element impact cache, if it is
/// no longer needed.
void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
{Element impactSource});
void applyImpact(WorldImpact worldImpact, {Element impactSource});
bool checkNoEnqueuedInvokedInstanceMethods();
void logSummary(log(message));
@ -148,8 +163,6 @@ class ResolutionEnqueuer extends Enqueuer {
WorldImpactVisitor impactVisitor;
ImpactStrategy impactStrategy;
ResolutionEnqueuer(
this.task,
this.options,
@ -194,8 +207,8 @@ class ResolutionEnqueuer extends Enqueuer {
internalAddToWorkList(element);
}
void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
{Element impactSource}) {
void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
impactSource, worldImpact, impactVisitor, impactUse);
}
@ -219,7 +232,7 @@ class ResolutionEnqueuer extends Enqueuer {
isNative: isNative,
byMirrors: mirrorUsage,
isRedirection: isRedirection, onImplemented: (ClassElement cls) {
backend.registerImplementedClass(cls, this);
applyImpact(backend.registerImplementedClass(cls, forResolution: true));
});
if (globalDependency && !mirrorUsage) {
globalDependencies.registerDependency(type.element);
@ -284,7 +297,7 @@ class ResolutionEnqueuer extends Enqueuer {
registerNoSuchMethod(function);
}
if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) {
registerCallMethodWithFreeTypeVariables(function);
_registerCallMethodWithFreeTypeVariables(function);
}
// If there is a property access with the same name as a method we
// need to emit the method.
@ -349,7 +362,8 @@ class ResolutionEnqueuer extends Enqueuer {
// We only tell the backend once that [superclass] was instantiated, so
// any additional dependencies must be treated as global
// dependencies.
backend.registerInstantiatedClass(superclass, this);
applyImpact(
backend.registerInstantiatedClass(superclass, forResolution: true));
}
ClassElement superclass = cls;
@ -433,11 +447,11 @@ class ResolutionEnqueuer extends Enqueuer {
assert(invariant(element, element.isDeclaration,
message: "Element ${element} is not the declaration."));
_universe.registerStaticUse(staticUse);
backend.registerStaticUse(this, element);
applyImpact(backend.registerStaticUse(element, forResolution: true));
bool addElement = true;
switch (staticUse.kind) {
case StaticUseKind.STATIC_TEAR_OFF:
backend.registerGetOfStaticFunction(this);
applyImpact(backend.registerGetOfStaticFunction());
break;
case StaticUseKind.FIELD_GET:
case StaticUseKind.FIELD_SET:
@ -514,18 +528,20 @@ class ResolutionEnqueuer extends Enqueuer {
assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
}
void registerCallMethodWithFreeTypeVariables(Element element) {
backend.registerCallMethodWithFreeTypeVariables(element, this);
void _registerCallMethodWithFreeTypeVariables(Element element) {
applyImpact(backend.registerCallMethodWithFreeTypeVariables(element,
forResolution: true));
_universe.callMethodsWithFreeTypeVariables.add(element);
}
void registerClosurizedMember(TypedElement element) {
assert(element.isInstanceMember);
if (element.computeType(resolution).containsTypeVariables) {
backend.registerClosureWithFreeTypeVariables(element, this);
applyImpact(backend.registerClosureWithFreeTypeVariables(element,
forResolution: true));
_universe.closuresWithFreeTypeVariables.add(element);
}
backend.registerBoundClosure(this);
applyImpact(backend.registerBoundClosure());
_universe.closurizedMembers.add(element);
}
@ -625,7 +641,7 @@ class ResolutionEnqueuer extends Enqueuer {
// runtime type.
_universe.hasRuntimeTypeSupport = true;
// TODO(ahe): Record precise dependency here.
backend.registerRuntimeType(this);
applyImpact(backend.registerRuntimeType());
} else if (commonElements.isFunctionApplyMethod(element)) {
_universe.hasFunctionApplySupport = true;
}
@ -639,7 +655,7 @@ class ResolutionEnqueuer extends Enqueuer {
void enableIsolateSupport() {
_universe.hasIsolateSupport = true;
backend.enableIsolateSupport(this);
applyImpact(backend.enableIsolateSupport(forResolution: true));
}
/**

View file

@ -335,7 +335,6 @@ class JavaScriptBackend extends Backend {
static const String TRACE_METHOD = const String.fromEnvironment('traceCalls');
static const bool TRACE_CALLS =
TRACE_METHOD == 'post' || TRACE_METHOD == 'console';
MethodElement traceHelper;
TypeMask get stringType => compiler.closedWorld.commonMasks.stringType;
TypeMask get doubleType => compiler.closedWorld.commonMasks.doubleType;
@ -1036,9 +1035,9 @@ class JavaScriptBackend extends Backend {
});
}
void addInterceptorsForNativeClassMembers(
ClassElement cls, Enqueuer enqueuer) {
if (enqueuer.isResolutionQueue) {
void addInterceptorsForNativeClassMembers(ClassElement cls,
{bool forResolution}) {
if (forResolution) {
cls.ensureResolved(resolution);
cls.forEachMember((ClassElement classElement, Element member) {
if (member.name == Identifiers.call) {
@ -1062,20 +1061,22 @@ class JavaScriptBackend extends Backend {
}
}
void addInterceptors(ClassElement cls, Enqueuer enqueuer) {
if (enqueuer.isResolutionQueue) {
void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder,
{bool forResolution}) {
if (forResolution) {
if (_interceptedClasses.add(cls)) {
cls.ensureResolved(resolution);
cls.forEachMember((ClassElement classElement, Element member) {
// All methods on [Object] are shadowed by [Interceptor].
if (classElement == coreClasses.objectClass) return;
Set<Element> set = interceptedElements.putIfAbsent(
member.name, () => new Set<Element>());
set.add(member);
}, includeSuperAndInjectedMembers: true);
}
_interceptedClasses.add(helpers.jsInterceptorClass);
_interceptedClasses.add(cls);
cls.ensureResolved(resolution);
cls.forEachMember((ClassElement classElement, Element member) {
// All methods on [Object] are shadowed by [Interceptor].
if (classElement == coreClasses.objectClass) return;
Set<Element> set = interceptedElements.putIfAbsent(
member.name, () => new Set<Element>());
set.add(member);
}, includeSuperAndInjectedMembers: true);
}
enqueueClass(enqueuer, cls);
impactTransformer.registerBackendInstantiation(impactBuilder, cls);
}
Set<ClassElement> get interceptedClasses {
@ -1168,190 +1169,168 @@ class JavaScriptBackend extends Backend {
}
}
void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) {
_processClass(cls, enqueuer);
WorldImpact registerInstantiatedClass(ClassElement cls,
{bool forResolution}) {
return _processClass(cls, forResolution: forResolution);
}
void registerImplementedClass(ClassElement cls, Enqueuer enqueuer) {
_processClass(cls, enqueuer);
WorldImpact registerImplementedClass(ClassElement cls, {bool forResolution}) {
return _processClass(cls, forResolution: forResolution);
}
void _processClass(ClassElement cls, Enqueuer enqueuer) {
WorldImpact _processClass(ClassElement cls, {bool forResolution}) {
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
if (!cls.typeVariables.isEmpty) {
typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer);
typeVariableHandler.registerClassWithTypeVariables(cls,
forResolution: forResolution);
}
// Register any helper that will be needed by the backend.
if (enqueuer.isResolutionQueue) {
if (forResolution) {
if (cls == coreClasses.intClass ||
cls == coreClasses.doubleClass ||
cls == coreClasses.numClass) {
// The backend will try to optimize number operations and use the
// `iae` helper directly.
enqueue(enqueuer, helpers.throwIllegalArgumentException);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.numClasses);
} else if (cls == coreClasses.listClass ||
cls == coreClasses.stringClass) {
// The backend will try to optimize array and string access and use the
// `ioore` and `iae` helpers directly.
enqueue(enqueuer, helpers.throwIndexOutOfRangeException);
enqueue(enqueuer, helpers.throwIllegalArgumentException);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.listOrStringClasses);
} else if (cls == coreClasses.functionClass) {
enqueueClass(enqueuer, helpers.closureClass);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.functionClass);
} else if (cls == coreClasses.mapClass) {
// The backend will use a literal list to initialize the entries
// of the map.
enqueueClass(enqueuer, coreClasses.listClass);
enqueueClass(enqueuer, helpers.mapLiteralClass);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.mapClass);
// For map literals, the dependency between the implementation class
// and [Map] is not visible, so we have to add it manually.
rti.registerRtiDependency(helpers.mapLiteralClass, cls);
} else if (cls == helpers.boundClosureClass) {
// TODO(johnniwinther): Is this a noop?
enqueueClass(enqueuer, helpers.boundClosureClass);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.boundClosureClass);
} else if (isNativeOrExtendsNative(cls)) {
enqueue(enqueuer, helpers.getNativeInterceptorMethod);
enqueueClass(enqueuer, helpers.jsInterceptorClass);
enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass);
enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass);
enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.nativeOrExtendsClass);
} else if (cls == helpers.mapLiteralClass) {
// For map literals, the dependency between the implementation class
// and [Map] is not visible, so we have to add it manually.
Element getFactory(String name, int arity) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
ClassElement implementation = cls.implementation;
ConstructorElement ctor = implementation.lookupConstructor(name);
if (ctor == null ||
(Name.isPrivateName(name) &&
ctor.library != helpers.mapLiteralClass.library)) {
reporter.internalError(
helpers.mapLiteralClass,
"Map literal class ${helpers.mapLiteralClass} missing "
"'$name' constructor"
" ${helpers.mapLiteralClass.constructors}");
}
return ctor;
}
Element getMember(String name) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
ClassElement implementation = cls.implementation;
Element element = implementation.lookupLocalMember(name);
if (element == null || !element.isFunction || !element.isStatic) {
reporter.internalError(
helpers.mapLiteralClass,
"Map literal class ${helpers.mapLiteralClass} missing "
"'$name' static member function");
}
return element;
}
helpers.mapLiteralConstructor = getFactory('_literal', 1);
helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0);
enqueue(enqueuer, helpers.mapLiteralConstructor);
enqueue(enqueuer, helpers.mapLiteralConstructorEmpty);
helpers.mapLiteralUntypedMaker = getMember('_makeLiteral');
helpers.mapLiteralUntypedEmptyMaker = getMember('_makeEmpty');
enqueue(enqueuer, helpers.mapLiteralUntypedMaker);
enqueue(enqueuer, helpers.mapLiteralUntypedEmptyMaker);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.mapLiteralClass);
}
}
if (cls == helpers.closureClass) {
enqueue(enqueuer, helpers.closureFromTearOff);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.closureClass);
}
if (cls == coreClasses.stringClass || cls == helpers.jsStringClass) {
addInterceptors(helpers.jsStringClass, enqueuer);
addInterceptors(helpers.jsStringClass, impactBuilder,
forResolution: forResolution);
} else if (cls == coreClasses.listClass ||
cls == helpers.jsArrayClass ||
cls == helpers.jsFixedArrayClass ||
cls == helpers.jsExtendableArrayClass ||
cls == helpers.jsUnmodifiableArrayClass) {
addInterceptors(helpers.jsArrayClass, enqueuer);
addInterceptors(helpers.jsMutableArrayClass, enqueuer);
addInterceptors(helpers.jsFixedArrayClass, enqueuer);
addInterceptors(helpers.jsExtendableArrayClass, enqueuer);
addInterceptors(helpers.jsUnmodifiableArrayClass, enqueuer);
if (enqueuer.isResolutionQueue) {
// Literal lists can be translated into calls to these functions:
enqueue(enqueuer, helpers.jsArrayTypedConstructor);
enqueue(enqueuer, helpers.setRuntimeTypeInfo);
enqueue(enqueuer, helpers.getTypeArgumentByIndex);
addInterceptors(helpers.jsArrayClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsMutableArrayClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsFixedArrayClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsExtendableArrayClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsUnmodifiableArrayClass, impactBuilder,
forResolution: forResolution);
if (forResolution) {
impactTransformer.registerBackendImpact(
impactBuilder, impacts.listClasses);
}
} else if (cls == coreClasses.intClass || cls == helpers.jsIntClass) {
addInterceptors(helpers.jsIntClass, enqueuer);
addInterceptors(helpers.jsPositiveIntClass, enqueuer);
addInterceptors(helpers.jsUInt32Class, enqueuer);
addInterceptors(helpers.jsUInt31Class, enqueuer);
addInterceptors(helpers.jsNumberClass, enqueuer);
addInterceptors(helpers.jsIntClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsPositiveIntClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsUInt32Class, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsUInt31Class, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsNumberClass, impactBuilder,
forResolution: forResolution);
} else if (cls == coreClasses.doubleClass || cls == helpers.jsDoubleClass) {
addInterceptors(helpers.jsDoubleClass, enqueuer);
addInterceptors(helpers.jsNumberClass, enqueuer);
addInterceptors(helpers.jsDoubleClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsNumberClass, impactBuilder,
forResolution: forResolution);
} else if (cls == coreClasses.boolClass || cls == helpers.jsBoolClass) {
addInterceptors(helpers.jsBoolClass, enqueuer);
addInterceptors(helpers.jsBoolClass, impactBuilder,
forResolution: forResolution);
} else if (cls == coreClasses.nullClass || cls == helpers.jsNullClass) {
addInterceptors(helpers.jsNullClass, enqueuer);
addInterceptors(helpers.jsNullClass, impactBuilder,
forResolution: forResolution);
} else if (cls == coreClasses.numClass || cls == helpers.jsNumberClass) {
addInterceptors(helpers.jsIntClass, enqueuer);
addInterceptors(helpers.jsPositiveIntClass, enqueuer);
addInterceptors(helpers.jsUInt32Class, enqueuer);
addInterceptors(helpers.jsUInt31Class, enqueuer);
addInterceptors(helpers.jsDoubleClass, enqueuer);
addInterceptors(helpers.jsNumberClass, enqueuer);
addInterceptors(helpers.jsIntClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsPositiveIntClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsUInt32Class, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsUInt31Class, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsDoubleClass, impactBuilder,
forResolution: forResolution);
addInterceptors(helpers.jsNumberClass, impactBuilder,
forResolution: forResolution);
} else if (cls == helpers.jsJavaScriptObjectClass) {
addInterceptors(helpers.jsJavaScriptObjectClass, enqueuer);
addInterceptors(helpers.jsJavaScriptObjectClass, impactBuilder,
forResolution: forResolution);
} else if (cls == helpers.jsPlainJavaScriptObjectClass) {
addInterceptors(helpers.jsPlainJavaScriptObjectClass, enqueuer);
addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder,
forResolution: forResolution);
} else if (cls == helpers.jsUnknownJavaScriptObjectClass) {
addInterceptors(helpers.jsUnknownJavaScriptObjectClass, enqueuer);
addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder,
forResolution: forResolution);
} else if (cls == helpers.jsJavaScriptFunctionClass) {
addInterceptors(helpers.jsJavaScriptFunctionClass, enqueuer);
addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder,
forResolution: forResolution);
} else if (isNativeOrExtendsNative(cls)) {
addInterceptorsForNativeClassMembers(cls, enqueuer);
addInterceptorsForNativeClassMembers(cls, forResolution: forResolution);
} else if (cls == helpers.jsIndexingBehaviorInterface) {
// These two helpers are used by the emitter and the codegen.
// Because we cannot enqueue elements at the time of emission,
// we make sure they are always generated.
enqueue(enqueuer, helpers.isJsIndexable);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.jsIndexingBehavior);
}
customElementsAnalysis.registerInstantiatedClass(cls,
forResolution: enqueuer.isResolutionQueue);
if (!enqueuer.isResolutionQueue) {
forResolution: forResolution);
if (!forResolution) {
lookupMapAnalysis.registerInstantiatedClass(cls);
}
return impactBuilder;
}
void registerInstantiatedType(InterfaceType type) {
lookupMapAnalysis.registerInstantiatedType(type);
}
void enqueueHelpers(ResolutionEnqueuer enqueuer) {
@override
WorldImpact computeHelpersImpact() {
assert(helpers.interceptorsLibrary != null);
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
// TODO(ngeoffray): Not enqueuing those two classes currently make
// the compiler potentially crash. However, any reasonable program
// will instantiate those two classes.
addInterceptors(helpers.jsBoolClass, enqueuer);
addInterceptors(helpers.jsNullClass, enqueuer);
addInterceptors(helpers.jsBoolClass, impactBuilder, forResolution: true);
addInterceptors(helpers.jsNullClass, impactBuilder, forResolution: true);
if (compiler.options.enableTypeAssertions) {
// Unconditionally register the helper that checks if the
// expression in an if/while/for is a boolean.
// TODO(ngeoffray): Should we have the resolver register those instead?
Element e = helpers.boolConversionCheck;
if (e != null) enqueue(enqueuer, e);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.enableTypeAssertions);
}
if (TRACE_CALLS) {
traceHelper = TRACE_METHOD == 'console'
? helpers.consoleTraceHelper
: helpers.postTraceHelper;
assert(traceHelper != null);
enqueue(enqueuer, traceHelper);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.traceHelper);
}
enqueue(enqueuer, helpers.assertUnreachableMethod);
registerCheckedModeHelpers(enqueuer);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.assertUnreachable);
_registerCheckedModeHelpers(impactBuilder);
return impactBuilder;
}
onResolutionComplete() {
@ -1366,47 +1345,36 @@ class JavaScriptBackend extends Backend {
noSuchMethodRegistry.onTypeInferenceComplete();
}
void registerGetRuntimeTypeArgument() {
enqueueImpact(compiler.enqueuer.resolution, impacts.getRuntimeTypeArgument);
}
void registerCallMethodWithFreeTypeVariables(
Element callMethod, Enqueuer enqueuer) {
if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) {
registerComputeSignature(enqueuer);
WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod,
{bool forResolution}) {
if (forResolution || methodNeedsRti(callMethod)) {
return _registerComputeSignature();
}
return const WorldImpact();
}
void registerClosureWithFreeTypeVariables(
Element closure, Enqueuer enqueuer) {
if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) {
registerComputeSignature(enqueuer);
WorldImpact registerClosureWithFreeTypeVariables(Element closure,
{bool forResolution}) {
if (forResolution || methodNeedsRti(closure)) {
return _registerComputeSignature();
}
return const WorldImpact();
}
void registerBoundClosure(Enqueuer enqueuer) {
helpers.boundClosureClass.ensureResolved(resolution);
enqueuer.registerInstantiatedType(helpers.boundClosureClass.rawType);
WorldImpact registerBoundClosure() {
return impactTransformer.createImpactFor(impacts.memberClosure);
}
void registerGetOfStaticFunction(Enqueuer enqueuer) {
helpers.closureClass.ensureResolved(resolution);
enqueuer.registerInstantiatedType(helpers.closureClass.rawType);
WorldImpact registerGetOfStaticFunction() {
return impactTransformer.createImpactFor(impacts.staticClosure);
}
void registerComputeSignature(Enqueuer enqueuer) {
// Calls to [:computeSignature:] are generated by the emitter and we
// therefore need to enqueue the used elements in the codegen enqueuer as
// well as in the resolution enqueuer.
enqueueImpact(enqueuer, impacts.computeSignature);
WorldImpact _registerComputeSignature() {
return impactTransformer.createImpactFor(impacts.computeSignature);
}
void registerRuntimeType(ResolutionEnqueuer enqueuer) {
registerComputeSignature(enqueuer);
enqueue(enqueuer, helpers.setRuntimeTypeInfo);
registerGetRuntimeTypeArgument();
enqueue(enqueuer, helpers.getRuntimeTypeInfo);
enqueueClass(enqueuer, coreClasses.listClass);
WorldImpact registerRuntimeType() {
return impactTransformer.createImpactFor(impacts.runtimeTypeSupport);
}
void registerTypeVariableBoundsSubtypeCheck(
@ -1414,10 +1382,8 @@ class JavaScriptBackend extends Backend {
rti.registerTypeVariableBoundsSubtypeCheck(typeArgument, bound);
}
void registerCheckDeferredIsLoaded(ResolutionEnqueuer enqueuer) {
enqueue(enqueuer, helpers.checkDeferredIsLoaded);
// Also register the types of the arguments passed to this method.
enqueueClass(enqueuer, coreClasses.stringClass);
WorldImpact computeDeferredLoadingImpact() {
return impactTransformer.createImpactFor(impacts.deferredLoading);
}
void registerNoSuchMethod(FunctionElement noSuchMethod) {
@ -1458,12 +1424,12 @@ class JavaScriptBackend extends Backend {
return null;
}
void enableNoSuchMethod(Enqueuer world) {
enqueue(world, helpers.createInvocationMirror);
world.registerDynamicUse(new DynamicUse(Selectors.noSuchMethod_, null));
WorldImpact enableNoSuchMethod() {
return impactTransformer.createImpactFor(impacts.noSuchMethodSupport);
}
void enableIsolateSupport(Enqueuer enqueuer) {
WorldImpact enableIsolateSupport({bool forResolution}) {
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
// TODO(floitsch): We should also ensure that the class IsolateMessage is
// instantiated. Currently, just enabling isolate support works.
if (compiler.mainFunction != null) {
@ -1474,22 +1440,16 @@ class JavaScriptBackend extends Backend {
// The JavaScript backend of [Isolate.spawnUri] uses the same internal
// implementation as [Isolate.spawn], and fails if it cannot look main up
// by name.
enqueuer.registerStaticUse(
impactBuilder.registerStaticUse(
new StaticUse.staticTearOff(compiler.mainFunction));
}
if (enqueuer.isResolutionQueue) {
void enqueue(Element element) {
enqueuer.addToWorkList(element);
compiler.globalDependencies.registerDependency(element);
helpersUsed.add(element.declaration);
}
enqueue(helpers.startRootIsolate);
enqueue(helpers.currentIsolate);
enqueue(helpers.callInIsolate);
} else {
enqueuer.addToWorkList(helpers.startRootIsolate);
impactTransformer.registerBackendImpact(
impactBuilder, impacts.isolateSupport);
if (forResolution) {
impactTransformer.registerBackendImpact(
impactBuilder, impacts.isolateSupportForResolution);
}
return impactBuilder;
}
bool classNeedsRti(ClassElement cls) {
@ -1519,60 +1479,6 @@ class JavaScriptBackend extends Backend {
compiler.resolverWorld.hasRuntimeTypeSupport;
}
/// Enqueue [e] in [enqueuer].
///
/// This method calls [registerBackendUse].
void enqueue(Enqueuer enqueuer, Element e) {
if (e == null) return;
registerBackendUse(e);
enqueuer.addToWorkList(e);
compiler.globalDependencies.registerDependency(e);
}
/// Register instantiation of [cls] in [enqueuer].
///
/// This method calls [registerBackendUse].
void enqueueClass(Enqueuer enqueuer, ClassElement cls) {
if (cls == null) return;
registerBackendUse(cls);
helpersUsed.add(cls.declaration);
if (cls.declaration != cls.implementation) {
helpersUsed.add(cls.implementation);
}
cls.ensureResolved(resolution);
enqueuer.registerInstantiatedType(cls.rawType);
}
/// Register instantiation of [type] in [enqueuer].
///
/// This method calls [registerBackendUse].
void enqueueType(Enqueuer enqueuer, InterfaceType type) {
if (type == null) return;
ClassElement cls = type.element;
registerBackendUse(cls);
helpersUsed.add(cls.declaration);
if (cls.declaration != cls.implementation) {
helpersUsed.add(cls.implementation);
}
cls.ensureResolved(resolution);
enqueuer.registerInstantiatedType(type);
}
void enqueueImpact(Enqueuer enqueuer, BackendImpact impact) {
for (Element staticUse in impact.staticUses) {
enqueue(enqueuer, staticUse);
}
for (InterfaceType type in impact.instantiatedTypes) {
enqueueType(enqueuer, type);
}
for (ClassElement cls in impact.instantiatedClasses) {
enqueueClass(enqueuer, cls);
}
for (BackendImpact otherImpact in impact.otherImpacts) {
enqueueImpact(enqueuer, otherImpact);
}
}
CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen;
CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) {
@ -1634,7 +1540,7 @@ class JavaScriptBackend extends Backend {
// go through the builder (below) to generate the lazy initializer for
// the static variable.
// We also need to register the use of the cyclic-error helper.
compiler.enqueuer.codegen.registerStaticUse(new StaticUse.staticInvoke(
work.registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
helpers.cyclicThrowHelper, CallStructure.ONE_ARG));
}
}
@ -1856,12 +1762,15 @@ class JavaScriptBackend extends Backend {
}
}
void registerCheckedModeHelpers(ResolutionEnqueuer enqueuer) {
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) {
enqueue(enqueuer, helper.getStaticUse(compiler).element);
staticUses.add(helper.getStaticUse(compiler).element);
}
impactTransformer.registerBackendImpact(
impactBuilder, new BackendImpact(globalUses: staticUses));
}
/**
@ -1892,7 +1801,8 @@ class JavaScriptBackend extends Backend {
return compiler.closedWorld.hasOnlySubclasses(classElement);
}
void registerStaticUse(Enqueuer enqueuer, Element element) {
WorldImpact registerStaticUse(Element element, {bool forResolution}) {
WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl();
if (element == helpers.disableTreeShakingMarker) {
isTreeShakingDisabled = true;
} else if (element == helpers.preserveNamesMarker) {
@ -1909,15 +1819,17 @@ class JavaScriptBackend extends Backend {
// TODO(sigurdm): Create a function registerLoadLibraryAccess.
if (!isLoadLibraryFunctionResolved) {
isLoadLibraryFunctionResolved = true;
if (enqueuer.isResolutionQueue) {
enqueue(enqueuer, helpers.loadLibraryWrapper);
if (forResolution) {
impactTransformer.registerBackendImpact(
worldImpact, impacts.loadLibrary);
}
}
} else if (element == helpers.requiresPreambleMarker) {
requiresPreamble = true;
}
customElementsAnalysis.registerStaticUse(element,
forResolution: enqueuer.isResolutionQueue);
forResolution: forResolution);
return worldImpact;
}
/// Called when [:const Symbol(name):] is seen.
@ -2344,13 +2256,11 @@ class JavaScriptBackend extends Backend {
//
// Return early if any elements are added to avoid counting the elements as
// due to mirrors.
enqueuer.applyImpact(customElementsAnalysis.flush(
forResolution: enqueuer.isResolutionQueue));
enqueuer.applyImpact(
compiler.impactStrategy,
customElementsAnalysis.flush(
forResolution: enqueuer.isResolutionQueue));
enqueuer.applyImpact(compiler.impactStrategy,
lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue));
enqueuer.applyImpact(compiler.impactStrategy,
enqueuer.applyImpact(
typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue));
if (!enqueuer.queueIsEmpty) return false;
@ -2359,7 +2269,7 @@ class JavaScriptBackend extends Backend {
if (!enabledNoSuchMethod &&
(noSuchMethodRegistry.hasThrowingNoSuchMethod ||
noSuchMethodRegistry.hasComplexNoSuchMethod)) {
enableNoSuchMethod(enqueuer);
enqueuer.applyImpact(enableNoSuchMethod());
enabledNoSuchMethod = true;
}
@ -2369,10 +2279,10 @@ class JavaScriptBackend extends Backend {
if (compiler.options.hasIncrementalSupport) {
// Always enable tear-off closures during incremental compilation.
Element e = helpers.closureFromTearOff;
if (e != null && !enqueuer.isProcessed(e)) {
registerBackendUse(e);
enqueuer.addToWorkList(e);
Element element = helpers.closureFromTearOff;
if (element != null && !enqueuer.isProcessed(element)) {
enqueuer.applyImpact(
impactTransformer.createImpactFor(impacts.closureClass));
}
}
@ -2381,19 +2291,17 @@ class JavaScriptBackend extends Backend {
}
if (isTreeShakingDisabled) {
enqueuer.applyImpact(
compiler.impactStrategy,
mirrorsAnalysis.computeImpactForReflectiveElements(recentClasses,
enqueuer.processedClasses, compiler.libraryLoader.libraries,
forResolution: enqueuer.isResolutionQueue));
enqueuer.applyImpact(mirrorsAnalysis.computeImpactForReflectiveElements(
recentClasses,
enqueuer.processedClasses,
compiler.libraryLoader.libraries,
forResolution: enqueuer.isResolutionQueue));
} else if (!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.
enqueuer.applyImpact(
compiler.impactStrategy,
mirrorsAnalysis.computeImpactForReflectiveStaticFields(
_findStaticFieldTargets(),
enqueuer.applyImpact(mirrorsAnalysis
.computeImpactForReflectiveStaticFields(_findStaticFieldTargets(),
forResolution: enqueuer.isResolutionQueue));
}
@ -2430,7 +2338,7 @@ class JavaScriptBackend extends Backend {
}
metadataConstants.clear();
}
enqueuer.applyImpact(compiler.impactStrategy, impactBuilder.flush());
enqueuer.applyImpact(impactBuilder.flush());
}
return true;
}
@ -2579,7 +2487,8 @@ class JavaScriptBackend extends Backend {
}
@override
WorldImpact computeMainImpact(Enqueuer enqueuer, MethodElement mainMethod) {
WorldImpact computeMainImpact(MethodElement mainMethod,
{bool forResolution}) {
WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
if (mainMethod.parameters.isNotEmpty) {
impactTransformer.registerBackendImpact(
@ -2590,7 +2499,7 @@ class JavaScriptBackend extends Backend {
// target of Isolate.spawnUri. Strictly speaking, that can happen also if
// main takes no arguments, but in this case the spawned isolate can't
// communicate with the spawning isolate.
enqueuer.enableIsolateSupport();
mainImpact.addImpact(enableIsolateSupport(forResolution: forResolution));
}
mainImpact.registerStaticUse(
new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
@ -2612,11 +2521,7 @@ class JavaScriptBackend extends Backend {
}
@override
bool enableDeferredLoadingIfSupported(
ResolutionEnqueuer enqueuer, Spannable node) {
registerCheckDeferredIsLoaded(enqueuer);
return true;
}
bool enableDeferredLoadingIfSupported(Spannable node) => true;
@override
bool enableCodegenWithErrorsIfSupported(Spannable node) => true;
@ -3011,14 +2916,44 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
return transformed;
}
WorldImpact createImpactFor(BackendImpact impact) {
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
registerBackendImpact(impactBuilder, impact);
return impactBuilder;
}
void registerBackendStaticUse(
WorldImpactBuilder worldImpact, MethodElement element,
{bool isGlobal: false}) {
backend.registerBackendUse(element);
worldImpact.registerStaticUse(
// TODO(johnniwinther): Store the correct use in impacts.
new StaticUse.foreignUse(element));
if (isGlobal) {
backend.compiler.globalDependencies.registerDependency(element);
}
}
void registerBackendInstantiation(
WorldImpactBuilder worldImpact, ClassElement cls,
{bool isGlobal: false}) {
cls.ensureResolved(backend.resolution);
backend.registerBackendUse(cls);
worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType));
if (isGlobal) {
backend.compiler.globalDependencies.registerDependency(cls);
}
}
void registerBackendImpact(
WorldImpactBuilder worldImpact, BackendImpact backendImpact) {
for (Element staticUse in backendImpact.staticUses) {
assert(staticUse != null);
backend.registerBackendUse(staticUse);
worldImpact.registerStaticUse(
// TODO(johnniwinther): Store the correct use in impacts.
new StaticUse.foreignUse(staticUse));
registerBackendStaticUse(worldImpact, staticUse);
}
for (Element staticUse in backendImpact.globalUses) {
assert(staticUse != null);
registerBackendStaticUse(worldImpact, staticUse, isGlobal: true);
}
for (Selector selector in backendImpact.dynamicUses) {
assert(selector != null);
@ -3029,9 +2964,10 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType));
}
for (ClassElement cls in backendImpact.instantiatedClasses) {
cls.ensureResolved(backend.resolution);
backend.registerBackendUse(cls);
worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType));
registerBackendInstantiation(worldImpact, cls);
}
for (ClassElement cls in backendImpact.globalClasses) {
registerBackendInstantiation(worldImpact, cls, isGlobal: true);
}
for (BackendImpact otherImpact in backendImpact.otherImpacts) {
registerBackendImpact(worldImpact, otherImpact);

View file

@ -21,6 +21,7 @@ import '../elements/elements.dart'
LibraryElement,
MemberElement,
MethodElement,
Name,
PublicName;
import '../library_loader.dart' show LoadedLibraries;
import '../universe/call_structure.dart' show CallStructure;
@ -120,10 +121,6 @@ class BackendHelpers {
ClassElement mapLiteralClass;
ClassElement constMapLiteralClass;
ClassElement typeVariableClass;
ConstructorElement mapLiteralConstructor;
ConstructorElement mapLiteralConstructorEmpty;
Element mapLiteralUntypedMaker;
Element mapLiteralUntypedEmptyMaker;
ClassElement noSideEffectsClass;
ClassElement noThrowsClass;
@ -396,6 +393,73 @@ class BackendHelpers {
objectEquals = compiler.lookupElementIn(coreClasses.objectClass, '==');
}
ConstructorElement _mapLiteralConstructor;
ConstructorElement _mapLiteralConstructorEmpty;
Element _mapLiteralUntypedMaker;
Element _mapLiteralUntypedEmptyMaker;
ConstructorElement get mapLiteralConstructor {
_ensureMapLiteralHelpers();
return _mapLiteralConstructor;
}
ConstructorElement get mapLiteralConstructorEmpty {
_ensureMapLiteralHelpers();
return _mapLiteralConstructorEmpty;
}
Element get mapLiteralUntypedMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedMaker;
}
Element get mapLiteralUntypedEmptyMaker {
_ensureMapLiteralHelpers();
return _mapLiteralUntypedEmptyMaker;
}
void _ensureMapLiteralHelpers() {
if (_mapLiteralConstructor != null) return;
// For map literals, the dependency between the implementation class
// and [Map] is not visible, so we have to add it manually.
Element getFactory(String name, int arity) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
ClassElement implementation = mapLiteralClass.implementation;
ConstructorElement ctor = implementation.lookupConstructor(name);
if (ctor == null ||
(Name.isPrivateName(name) &&
ctor.library != mapLiteralClass.library)) {
reporter.internalError(
mapLiteralClass,
"Map literal class ${mapLiteralClass} missing "
"'$name' constructor"
" ${mapLiteralClass.constructors}");
}
return ctor;
}
Element getMember(String name) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
ClassElement implementation = mapLiteralClass.implementation;
Element element = implementation.lookupLocalMember(name);
if (element == null || !element.isFunction || !element.isStatic) {
reporter.internalError(
mapLiteralClass,
"Map literal class ${mapLiteralClass} missing "
"'$name' static member function");
}
return element;
}
_mapLiteralConstructor = getFactory('_literal', 1);
_mapLiteralConstructorEmpty = getFactory('_empty', 0);
_mapLiteralUntypedMaker = getMember('_makeLiteral');
_mapLiteralUntypedEmptyMaker = getMember('_makeEmpty');
}
Element get badMain {
return findHelper('badMain');
}
@ -416,11 +480,19 @@ class BackendHelpers {
return findHelper('boolConversionCheck');
}
Element get consoleTraceHelper {
MethodElement _traceHelper;
MethodElement get traceHelper {
return _traceHelper ??= JavaScriptBackend.TRACE_METHOD == 'console'
? _consoleTraceHelper
: _postTraceHelper;
}
MethodElement get _consoleTraceHelper {
return findHelper('consoleTraceHelper');
}
Element get postTraceHelper {
MethodElement get _postTraceHelper {
return findHelper('postTraceHelper');
}

View file

@ -24,17 +24,21 @@ enum BackendFeature {
/// A set of JavaScript backend dependencies.
class BackendImpact {
final List<Element> staticUses;
final List<Element> globalUses;
final List<Selector> dynamicUses;
final List<InterfaceType> instantiatedTypes;
final List<ClassElement> instantiatedClasses;
final List<ClassElement> globalClasses;
final List<BackendImpact> otherImpacts;
final EnumSet<BackendFeature> _features;
const BackendImpact(
{this.staticUses: const <Element>[],
this.globalUses: const <Element>[],
this.dynamicUses: const <Selector>[],
this.instantiatedTypes: const <InterfaceType>[],
this.instantiatedClasses: const <ClassElement>[],
this.globalClasses: const <ClassElement>[],
this.otherImpacts: const <BackendImpact>[],
EnumSet<BackendFeature> features: const EnumSet<BackendFeature>.fixed(0)})
: this._features = features;
@ -58,172 +62,131 @@ class BackendImpacts {
BackendImpact _getRuntimeTypeArgument;
BackendImpact get getRuntimeTypeArgument {
if (_getRuntimeTypeArgument == null) {
_getRuntimeTypeArgument = new BackendImpact(staticUses: [
helpers.getRuntimeTypeArgument,
helpers.getTypeArgumentByIndex,
]);
}
return _getRuntimeTypeArgument;
return _getRuntimeTypeArgument ??= new BackendImpact(globalUses: [
helpers.getRuntimeTypeArgument,
helpers.getTypeArgumentByIndex,
]);
}
BackendImpact _computeSignature;
BackendImpact get computeSignature {
if (_computeSignature == null) {
_computeSignature = new BackendImpact(staticUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.computeSignature,
helpers.getRuntimeTypeArguments
], otherImpacts: [
listValues
]);
}
return _computeSignature;
return _computeSignature ??= new BackendImpact(globalUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.computeSignature,
helpers.getRuntimeTypeArguments
], otherImpacts: [
listValues
]);
}
BackendImpact _mainWithArguments;
BackendImpact get mainWithArguments {
if (_mainWithArguments == null) {
_mainWithArguments = new BackendImpact(
instantiatedClasses: [
helpers.jsArrayClass,
helpers.jsStringClass]);
}
return _mainWithArguments;
return _mainWithArguments ??= new BackendImpact(
instantiatedClasses: [helpers.jsArrayClass, helpers.jsStringClass]);
}
BackendImpact _asyncBody;
BackendImpact get asyncBody {
if (_asyncBody == null) {
_asyncBody = new BackendImpact(staticUses: [
helpers.asyncHelper,
helpers.syncCompleterConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody
]);
}
return _asyncBody;
return _asyncBody ??= new BackendImpact(staticUses: [
helpers.asyncHelper,
helpers.syncCompleterConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody
]);
}
BackendImpact _syncStarBody;
BackendImpact get syncStarBody {
if (_syncStarBody == null) {
_syncStarBody = new BackendImpact(staticUses: [
helpers.syncStarIterableConstructor,
helpers.endOfIteration,
helpers.yieldStar,
helpers.syncStarUncaughtError
], instantiatedClasses: [
helpers.syncStarIterable
]);
}
return _syncStarBody;
return _syncStarBody ??= new BackendImpact(staticUses: [
helpers.syncStarIterableConstructor,
helpers.endOfIteration,
helpers.yieldStar,
helpers.syncStarUncaughtError
], instantiatedClasses: [
helpers.syncStarIterable
]);
}
BackendImpact _asyncStarBody;
BackendImpact get asyncStarBody {
if (_asyncStarBody == null) {
_asyncStarBody = new BackendImpact(staticUses: [
helpers.asyncStarHelper,
helpers.streamOfController,
helpers.yieldSingle,
helpers.yieldStar,
helpers.asyncStarControllerConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody
], instantiatedClasses: [
helpers.asyncStarController
]);
}
return _asyncStarBody;
return _asyncStarBody ??= new BackendImpact(staticUses: [
helpers.asyncStarHelper,
helpers.streamOfController,
helpers.yieldSingle,
helpers.yieldStar,
helpers.asyncStarControllerConstructor,
helpers.streamIteratorConstructor,
helpers.wrapBody
], instantiatedClasses: [
helpers.asyncStarController
]);
}
BackendImpact _typeVariableBoundCheck;
BackendImpact get typeVariableBoundCheck {
if (_typeVariableBoundCheck == null) {
_typeVariableBoundCheck = new BackendImpact(
staticUses: [helpers.throwTypeError, helpers.assertIsSubtype]);
}
return _typeVariableBoundCheck;
return _typeVariableBoundCheck ??= new BackendImpact(
staticUses: [helpers.throwTypeError, helpers.assertIsSubtype]);
}
BackendImpact _abstractClassInstantiation;
BackendImpact get abstractClassInstantiation {
if (_abstractClassInstantiation == null) {
_abstractClassInstantiation = new BackendImpact(
staticUses: [helpers.throwAbstractClassInstantiationError],
otherImpacts: [_needsString('Needed to encode the message.')]);
}
return _abstractClassInstantiation;
return _abstractClassInstantiation ??= new BackendImpact(
staticUses: [helpers.throwAbstractClassInstantiationError],
otherImpacts: [_needsString('Needed to encode the message.')]);
}
BackendImpact _fallThroughError;
BackendImpact get fallThroughError {
if (_fallThroughError == null) {
_fallThroughError =
new BackendImpact(staticUses: [helpers.fallThroughError]);
}
return _fallThroughError;
return _fallThroughError ??=
new BackendImpact(staticUses: [helpers.fallThroughError]);
}
BackendImpact _asCheck;
BackendImpact get asCheck {
if (_asCheck == null) {
_asCheck = new BackendImpact(staticUses: [helpers.throwRuntimeError]);
}
return _asCheck;
return _asCheck ??=
new BackendImpact(staticUses: [helpers.throwRuntimeError]);
}
BackendImpact _throwNoSuchMethod;
BackendImpact get throwNoSuchMethod {
if (_throwNoSuchMethod == null) {
_throwNoSuchMethod = new BackendImpact(staticUses: [
helpers.throwNoSuchMethod
], otherImpacts: [
// Also register the types of the arguments passed to this method.
_needsList(
'Needed to encode the arguments for throw NoSuchMethodError.'),
_needsString('Needed to encode the name for throw NoSuchMethodError.')
]);
}
return _throwNoSuchMethod;
return _throwNoSuchMethod ??= new BackendImpact(staticUses: [
helpers.throwNoSuchMethod
], otherImpacts: [
// Also register the types of the arguments passed to this method.
_needsList('Needed to encode the arguments for throw NoSuchMethodError.'),
_needsString('Needed to encode the name for throw NoSuchMethodError.')
]);
}
BackendImpact _stringValues;
BackendImpact get stringValues {
if (_stringValues == null) {
_stringValues =
new BackendImpact(instantiatedClasses: [helpers.jsStringClass]);
}
return _stringValues;
return _stringValues ??=
new BackendImpact(instantiatedClasses: [helpers.jsStringClass]);
}
BackendImpact _numValues;
BackendImpact get numValues {
if (_numValues == null) {
_numValues = new BackendImpact(instantiatedClasses: [
helpers.jsIntClass,
helpers.jsPositiveIntClass,
helpers.jsUInt32Class,
helpers.jsUInt31Class,
helpers.jsNumberClass,
helpers.jsDoubleClass
]);
}
return _numValues;
return _numValues ??= new BackendImpact(instantiatedClasses: [
helpers.jsIntClass,
helpers.jsPositiveIntClass,
helpers.jsUInt32Class,
helpers.jsUInt31Class,
helpers.jsNumberClass,
helpers.jsDoubleClass
]);
}
BackendImpact get intValues => numValues;
@ -233,67 +196,51 @@ class BackendImpacts {
BackendImpact _boolValues;
BackendImpact get boolValues {
if (_boolValues == null) {
_boolValues =
new BackendImpact(instantiatedClasses: [helpers.jsBoolClass]);
}
return _boolValues;
return _boolValues ??=
new BackendImpact(instantiatedClasses: [helpers.jsBoolClass]);
}
BackendImpact _nullValue;
BackendImpact get nullValue {
if (_nullValue == null) {
_nullValue =
new BackendImpact(instantiatedClasses: [helpers.jsNullClass]);
}
return _nullValue;
return _nullValue ??=
new BackendImpact(instantiatedClasses: [helpers.jsNullClass]);
}
BackendImpact _listValues;
BackendImpact get listValues {
if (_listValues == null) {
_listValues = new BackendImpact(instantiatedClasses: [
helpers.jsArrayClass,
helpers.jsMutableArrayClass,
helpers.jsFixedArrayClass,
helpers.jsExtendableArrayClass,
helpers.jsUnmodifiableArrayClass
]);
}
return _listValues;
return _listValues ??= new BackendImpact(globalClasses: [
helpers.jsArrayClass,
helpers.jsMutableArrayClass,
helpers.jsFixedArrayClass,
helpers.jsExtendableArrayClass,
helpers.jsUnmodifiableArrayClass
]);
}
BackendImpact _throwRuntimeError;
BackendImpact get throwRuntimeError {
if (_throwRuntimeError == null) {
_throwRuntimeError = new BackendImpact(staticUses: [
helpers.throwRuntimeError
], otherImpacts: [
// Also register the types of the arguments passed to this method.
stringValues
]);
}
return _throwRuntimeError;
return _throwRuntimeError ??= new BackendImpact(staticUses: [
helpers.throwRuntimeError
], otherImpacts: [
// Also register the types of the arguments passed to this method.
stringValues
]);
}
BackendImpact _superNoSuchMethod;
BackendImpact get superNoSuchMethod {
if (_superNoSuchMethod == null) {
_superNoSuchMethod = new BackendImpact(staticUses: [
helpers.createInvocationMirror,
helpers.objectNoSuchMethod
], otherImpacts: [
_needsInt(
'Needed to encode the invocation kind of super.noSuchMethod.'),
_needsList('Needed to encode the arguments of super.noSuchMethod.'),
_needsString('Needed to encode the name of super.noSuchMethod.')
]);
}
return _superNoSuchMethod;
return _superNoSuchMethod ??= new BackendImpact(staticUses: [
helpers.createInvocationMirror,
helpers.objectNoSuchMethod
], otherImpacts: [
_needsInt('Needed to encode the invocation kind of super.noSuchMethod.'),
_needsList('Needed to encode the arguments of super.noSuchMethod.'),
_needsString('Needed to encode the name of super.noSuchMethod.')
]);
}
BackendImpact _constantMapLiteral;
@ -317,22 +264,16 @@ class BackendImpacts {
BackendImpact _symbolConstructor;
BackendImpact get symbolConstructor {
if (_symbolConstructor == null) {
_symbolConstructor =
new BackendImpact(staticUses: [helpers.symbolValidatedConstructor]);
}
return _symbolConstructor;
return _symbolConstructor ??=
new BackendImpact(staticUses: [helpers.symbolValidatedConstructor]);
}
BackendImpact _constSymbol;
BackendImpact get constSymbol {
if (_constSymbol == null) {
_constSymbol = new BackendImpact(
instantiatedClasses: [commonElements.symbolClass],
staticUses: [commonElements.symbolConstructor.declaration]);
}
return _constSymbol;
return _constSymbol ??= new BackendImpact(
instantiatedClasses: [commonElements.symbolClass],
staticUses: [commonElements.symbolConstructor.declaration]);
}
/// Helper for registering that `int` is needed.
@ -356,52 +297,37 @@ class BackendImpacts {
BackendImpact _assertWithoutMessage;
BackendImpact get assertWithoutMessage {
if (_assertWithoutMessage == null) {
_assertWithoutMessage =
new BackendImpact(staticUses: [helpers.assertHelper]);
}
return _assertWithoutMessage;
return _assertWithoutMessage ??=
new BackendImpact(staticUses: [helpers.assertHelper]);
}
BackendImpact _assertWithMessage;
BackendImpact get assertWithMessage {
if (_assertWithMessage == null) {
_assertWithMessage = new BackendImpact(
staticUses: [helpers.assertTest, helpers.assertThrow]);
}
return _assertWithMessage;
return _assertWithMessage ??= new BackendImpact(
staticUses: [helpers.assertTest, helpers.assertThrow]);
}
BackendImpact _asyncForIn;
BackendImpact get asyncForIn {
if (_asyncForIn == null) {
_asyncForIn =
new BackendImpact(staticUses: [helpers.streamIteratorConstructor]);
}
return _asyncForIn;
return _asyncForIn ??=
new BackendImpact(staticUses: [helpers.streamIteratorConstructor]);
}
BackendImpact _stringInterpolation;
BackendImpact get stringInterpolation {
if (_stringInterpolation == null) {
_stringInterpolation = new BackendImpact(
dynamicUses: [Selectors.toString_],
staticUses: [helpers.stringInterpolationHelper],
otherImpacts: [_needsString('Strings are created.')]);
}
return _stringInterpolation;
return _stringInterpolation ??= new BackendImpact(
dynamicUses: [Selectors.toString_],
staticUses: [helpers.stringInterpolationHelper],
otherImpacts: [_needsString('Strings are created.')]);
}
BackendImpact _stringJuxtaposition;
BackendImpact get stringJuxtaposition {
if (_stringJuxtaposition == null) {
_stringJuxtaposition = _needsString('String.concat is used.');
}
return _stringJuxtaposition;
return _stringJuxtaposition ??= _needsString('String.concat is used.');
}
BackendImpact get nullLiteral => nullValue;
@ -417,231 +343,368 @@ class BackendImpacts {
BackendImpact _catchStatement;
BackendImpact get catchStatement {
if (_catchStatement == null) {
_catchStatement = new BackendImpact(staticUses: [
helpers.exceptionUnwrapper
], instantiatedClasses: [
helpers.jsPlainJavaScriptObjectClass,
helpers.jsUnknownJavaScriptObjectClass
]);
}
return _catchStatement;
return _catchStatement ??= new BackendImpact(staticUses: [
helpers.exceptionUnwrapper
], instantiatedClasses: [
helpers.jsPlainJavaScriptObjectClass,
helpers.jsUnknownJavaScriptObjectClass
]);
}
BackendImpact _throwExpression;
BackendImpact get throwExpression {
if (_throwExpression == null) {
_throwExpression = new BackendImpact(
// We don't know ahead of time whether we will need the throw in a
// statement context or an expression context, so we register both
// here, even though we may not need the throwExpression helper.
staticUses: [
helpers.wrapExceptionHelper,
helpers.throwExpressionHelper
]);
}
return _throwExpression;
return _throwExpression ??= new BackendImpact(
// We don't know ahead of time whether we will need the throw in a
// statement context or an expression context, so we register both
// here, even though we may not need the throwExpression helper.
staticUses: [
helpers.wrapExceptionHelper,
helpers.throwExpressionHelper
]);
}
BackendImpact _lazyField;
BackendImpact get lazyField {
if (_lazyField == null) {
_lazyField = new BackendImpact(staticUses: [helpers.cyclicThrowHelper]);
}
return _lazyField;
return _lazyField ??=
new BackendImpact(staticUses: [helpers.cyclicThrowHelper]);
}
BackendImpact _typeLiteral;
BackendImpact get typeLiteral {
if (_typeLiteral == null) {
_typeLiteral = new BackendImpact(
instantiatedClasses: [backend.backendClasses.typeImplementation],
staticUses: [helpers.createRuntimeType]);
}
return _typeLiteral;
return _typeLiteral ??= new BackendImpact(
instantiatedClasses: [backend.backendClasses.typeImplementation],
staticUses: [helpers.createRuntimeType]);
}
BackendImpact _stackTraceInCatch;
BackendImpact get stackTraceInCatch {
if (_stackTraceInCatch == null) {
_stackTraceInCatch = new BackendImpact(
instantiatedClasses: [helpers.stackTraceClass],
staticUses: [helpers.traceFromException]);
}
return _stackTraceInCatch;
return _stackTraceInCatch ??= new BackendImpact(
instantiatedClasses: [helpers.stackTraceClass],
staticUses: [helpers.traceFromException]);
}
BackendImpact _syncForIn;
BackendImpact get syncForIn {
if (_syncForIn == null) {
_syncForIn = new BackendImpact(
// The SSA builder recognizes certain for-in loops and can generate
// calls to throwConcurrentModificationError.
staticUses: [helpers.checkConcurrentModificationError]);
}
return _syncForIn;
return _syncForIn ??= new BackendImpact(
// The SSA builder recognizes certain for-in loops and can generate
// calls to throwConcurrentModificationError.
staticUses: [helpers.checkConcurrentModificationError]);
}
BackendImpact _typeVariableExpression;
BackendImpact get typeVariableExpression {
if (_typeVariableExpression == null) {
_typeVariableExpression = new BackendImpact(staticUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.runtimeTypeToString,
helpers.createRuntimeType
], otherImpacts: [
listValues,
getRuntimeTypeArgument,
_needsInt('Needed for accessing a type variable literal on this.')
]);
}
return _typeVariableExpression;
return _typeVariableExpression ??= new BackendImpact(staticUses: [
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo,
helpers.runtimeTypeToString,
helpers.createRuntimeType
], otherImpacts: [
listValues,
getRuntimeTypeArgument,
_needsInt('Needed for accessing a type variable literal on this.')
]);
}
BackendImpact _typeCheck;
BackendImpact get typeCheck {
if (_typeCheck == null) {
_typeCheck = new BackendImpact(otherImpacts: [boolValues]);
}
return _typeCheck;
return _typeCheck ??= new BackendImpact(otherImpacts: [boolValues]);
}
BackendImpact _checkedModeTypeCheck;
BackendImpact get checkedModeTypeCheck {
if (_checkedModeTypeCheck == null) {
_checkedModeTypeCheck =
new BackendImpact(staticUses: [helpers.throwRuntimeError]);
}
return _checkedModeTypeCheck;
return _checkedModeTypeCheck ??=
new BackendImpact(staticUses: [helpers.throwRuntimeError]);
}
BackendImpact _malformedTypeCheck;
BackendImpact get malformedTypeCheck {
if (_malformedTypeCheck == null) {
_malformedTypeCheck =
new BackendImpact(staticUses: [helpers.throwTypeError]);
}
return _malformedTypeCheck;
return _malformedTypeCheck ??=
new BackendImpact(staticUses: [helpers.throwTypeError]);
}
BackendImpact _genericTypeCheck;
BackendImpact get genericTypeCheck {
if (_genericTypeCheck == null) {
_genericTypeCheck = new BackendImpact(staticUses: [
helpers.checkSubtype,
// TODO(johnniwinther): Investigate why this is needed.
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo
], otherImpacts: [
listValues,
getRuntimeTypeArgument
]);
}
return _genericTypeCheck;
return _genericTypeCheck ??= new BackendImpact(staticUses: [
helpers.checkSubtype,
// TODO(johnniwinther): Investigate why this is needed.
helpers.setRuntimeTypeInfo,
helpers.getRuntimeTypeInfo
], otherImpacts: [
listValues,
getRuntimeTypeArgument
]);
}
BackendImpact _genericIsCheck;
BackendImpact get genericIsCheck {
if (_genericIsCheck == null) {
_genericIsCheck = new BackendImpact(otherImpacts: [intValues]);
}
return _genericIsCheck;
return _genericIsCheck ??= new BackendImpact(otherImpacts: [intValues]);
}
BackendImpact _genericCheckedModeTypeCheck;
BackendImpact get genericCheckedModeTypeCheck {
if (_genericCheckedModeTypeCheck == null) {
_genericCheckedModeTypeCheck =
new BackendImpact(staticUses: [helpers.assertSubtype]);
}
return _genericCheckedModeTypeCheck;
return _genericCheckedModeTypeCheck ??=
new BackendImpact(staticUses: [helpers.assertSubtype]);
}
BackendImpact _typeVariableTypeCheck;
BackendImpact get typeVariableTypeCheck {
if (_typeVariableTypeCheck == null) {
_typeVariableTypeCheck =
new BackendImpact(staticUses: [helpers.checkSubtypeOfRuntimeType]);
}
return _typeVariableTypeCheck;
return _typeVariableTypeCheck ??=
new BackendImpact(staticUses: [helpers.checkSubtypeOfRuntimeType]);
}
BackendImpact _typeVariableCheckedModeTypeCheck;
BackendImpact get typeVariableCheckedModeTypeCheck {
if (_typeVariableCheckedModeTypeCheck == null) {
_typeVariableCheckedModeTypeCheck =
new BackendImpact(staticUses: [helpers.assertSubtypeOfRuntimeType]);
}
return _typeVariableCheckedModeTypeCheck;
return _typeVariableCheckedModeTypeCheck ??=
new BackendImpact(staticUses: [helpers.assertSubtypeOfRuntimeType]);
}
BackendImpact _functionTypeCheck;
BackendImpact get functionTypeCheck {
if (_functionTypeCheck == null) {
_functionTypeCheck =
new BackendImpact(staticUses: [helpers.functionTypeTestMetaHelper]);
}
return _functionTypeCheck;
return _functionTypeCheck ??=
new BackendImpact(staticUses: [helpers.functionTypeTestMetaHelper]);
}
BackendImpact _nativeTypeCheck;
BackendImpact get nativeTypeCheck {
if (_nativeTypeCheck == null) {
_nativeTypeCheck = new BackendImpact(staticUses: [
// We will neeed to add the "$is" and "$as" properties on the
// JavaScript object prototype, so we make sure
// [:defineProperty:] is compiled.
helpers.defineProperty
]);
}
return _nativeTypeCheck;
return _nativeTypeCheck ??= new BackendImpact(staticUses: [
// We will neeed to add the "$is" and "$as" properties on the
// JavaScript object prototype, so we make sure
// [:defineProperty:] is compiled.
helpers.defineProperty
]);
}
BackendImpact _closure;
BackendImpact get closure {
if (_closure == null) {
_closure = new BackendImpact(
instantiatedClasses: [commonElements.functionClass]);
}
return _closure;
return _closure ??=
new BackendImpact(instantiatedClasses: [commonElements.functionClass]);
}
BackendImpact _interceptorUse;
BackendImpact get interceptorUse {
if (_interceptorUse == null) {
_interceptorUse = new BackendImpact(
staticUses: [
helpers.getNativeInterceptorMethod
],
instantiatedClasses: [
helpers.jsJavaScriptObjectClass,
helpers.jsPlainJavaScriptObjectClass,
helpers.jsJavaScriptFunctionClass
],
features: new EnumSet<BackendFeature>.fromValues([
BackendFeature.needToInitializeDispatchProperty,
BackendFeature.needToInitializeIsolateAffinityTag
], fixed: true));
}
return _interceptorUse;
return _interceptorUse ??= new BackendImpact(
staticUses: [
helpers.getNativeInterceptorMethod
],
instantiatedClasses: [
helpers.jsJavaScriptObjectClass,
helpers.jsPlainJavaScriptObjectClass,
helpers.jsJavaScriptFunctionClass
],
features: new EnumSet<BackendFeature>.fromValues([
BackendFeature.needToInitializeDispatchProperty,
BackendFeature.needToInitializeIsolateAffinityTag
], fixed: true));
}
BackendImpact _numClasses;
BackendImpact get numClasses {
return _numClasses ??= new BackendImpact(
// The backend will try to optimize number operations and use the
// `iae` helper directly.
globalUses: [helpers.throwIllegalArgumentException]);
}
BackendImpact _listOrStringClasses;
BackendImpact get listOrStringClasses {
return _listOrStringClasses ??= new BackendImpact(
// The backend will try to optimize array and string access and use the
// `ioore` and `iae` helpers directly.
globalUses: [
helpers.throwIndexOutOfRangeException,
helpers.throwIllegalArgumentException
]);
}
BackendImpact _functionClass;
BackendImpact get functionClass {
return _functionClass ??=
new BackendImpact(globalClasses: [helpers.closureClass]);
}
BackendImpact _mapClass;
BackendImpact get mapClass {
return _mapClass ??= new BackendImpact(
// The backend will use a literal list to initialize the entries
// of the map.
globalClasses: [
helpers.coreClasses.listClass,
helpers.mapLiteralClass
]);
}
BackendImpact _boundClosureClass;
BackendImpact get boundClosureClass {
return _boundClosureClass ??=
new BackendImpact(globalClasses: [helpers.boundClosureClass]);
}
BackendImpact _nativeOrExtendsClass;
BackendImpact get nativeOrExtendsClass {
return _nativeOrExtendsClass ??= new BackendImpact(globalUses: [
helpers.getNativeInterceptorMethod
], globalClasses: [
helpers.jsInterceptorClass,
helpers.jsJavaScriptObjectClass,
helpers.jsPlainJavaScriptObjectClass,
helpers.jsJavaScriptFunctionClass
]);
}
BackendImpact _mapLiteralClass;
BackendImpact get mapLiteralClass {
return _mapLiteralClass ??= new BackendImpact(globalUses: [
helpers.mapLiteralConstructor,
helpers.mapLiteralConstructorEmpty,
helpers.mapLiteralUntypedMaker,
helpers.mapLiteralUntypedEmptyMaker
]);
}
BackendImpact _closureClass;
BackendImpact get closureClass {
return _closureClass ??=
new BackendImpact(globalUses: [helpers.closureFromTearOff]);
}
BackendImpact _listClasses;
BackendImpact get listClasses {
return _listClasses ??= new BackendImpact(
// Literal lists can be translated into calls to these functions:
globalUses: [
helpers.jsArrayTypedConstructor,
helpers.setRuntimeTypeInfo,
helpers.getTypeArgumentByIndex
]);
}
BackendImpact _jsIndexingBehavior;
BackendImpact get jsIndexingBehavior {
return _jsIndexingBehavior ??= new BackendImpact(
// These two helpers are used by the emitter and the codegen.
// Because we cannot enqueue elements at the time of emission,
// we make sure they are always generated.
globalUses: [helpers.isJsIndexable]);
}
BackendImpact _enableTypeAssertions;
BackendImpact get enableTypeAssertions {
return _enableTypeAssertions ??= new BackendImpact(
// Register the helper that checks if the expression in an if/while/for
// is a boolean.
// TODO(johnniwinther): Should this be registered through a [Feature]
// instead?
globalUses: [helpers.boolConversionCheck]);
}
BackendImpact _traceHelper;
BackendImpact get traceHelper {
return _traceHelper ??=
new BackendImpact(globalUses: [helpers.traceHelper]);
}
BackendImpact _assertUnreachable;
BackendImpact get assertUnreachable {
return _assertUnreachable ??=
new BackendImpact(globalUses: [helpers.assertUnreachableMethod]);
}
BackendImpact _runtimeTypeSupport;
BackendImpact get runtimeTypeSupport {
return _runtimeTypeSupport ??= new BackendImpact(
globalClasses: [helpers.coreClasses.listClass],
globalUses: [helpers.setRuntimeTypeInfo, helpers.getRuntimeTypeInfo],
otherImpacts: [getRuntimeTypeArgument, computeSignature]);
}
BackendImpact _deferredLoading;
BackendImpact get deferredLoading {
return _deferredLoading ??=
new BackendImpact(globalUses: [helpers.checkDeferredIsLoaded],
// Also register the types of the arguments passed to this method.
globalClasses: [helpers.coreClasses.stringClass]);
}
BackendImpact _noSuchMethodSupport;
BackendImpact get noSuchMethodSupport {
return _noSuchMethodSupport ??= new BackendImpact(
staticUses: [helpers.createInvocationMirror],
dynamicUses: [Selectors.noSuchMethod_]);
}
BackendImpact _isolateSupport;
/// Backend impact for isolate support.
BackendImpact get isolateSupport {
return _isolateSupport ??=
new BackendImpact(globalUses: [helpers.startRootIsolate]);
}
BackendImpact _isolateSupportForResolution;
/// Additional backend impact for isolate support in resolution.
BackendImpact get isolateSupportForResolution {
return _isolateSupportForResolution ??= new BackendImpact(
globalUses: [helpers.currentIsolate, helpers.callInIsolate]);
}
BackendImpact _loadLibrary;
/// Backend impact for accessing a `loadLibrary` function on a deferred
/// prefix.
BackendImpact get loadLibrary {
return _loadLibrary ??=
new BackendImpact(globalUses: [helpers.loadLibraryWrapper]);
}
BackendImpact _memberClosure;
/// Backend impact for performing member closurization.
BackendImpact get memberClosure {
return _memberClosure ??=
new BackendImpact(globalClasses: [helpers.boundClosureClass]);
}
BackendImpact _staticClosure;
/// Backend impact for performing closurization of a top-level or static
/// function.
BackendImpact get staticClosure {
return _staticClosure ??=
new BackendImpact(globalClasses: [helpers.closureClass]);
}
}

View file

@ -43,7 +43,7 @@ import '../util/util.dart' show Setlet;
import '../world.dart';
/// [Enqueuer] which is specific to code generation.
class CodegenEnqueuer implements Enqueuer {
class CodegenEnqueuer extends Enqueuer {
final String name;
@deprecated
final Compiler _compiler; // TODO(ahe): Remove this dependency.
@ -123,8 +123,8 @@ class CodegenEnqueuer implements Enqueuer {
.registerDependency(_compiler.currentElement, element);
}
void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
{Element impactSource}) {
void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
impactSource, worldImpact, impactVisitor, impactUse);
}
@ -141,7 +141,8 @@ class CodegenEnqueuer implements Enqueuer {
_universe.registerTypeInstantiation(type,
isNative: isNative,
byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
backend.registerImplementedClass(cls, this);
applyImpact(
backend.registerImplementedClass(cls, forResolution: false));
});
if (nativeUsage) {
nativeEnqueuer.onInstantiatedType(type);
@ -272,7 +273,8 @@ class CodegenEnqueuer implements Enqueuer {
// We only tell the backend once that [superclass] was instantiated, so
// any additional dependencies must be treated as global
// dependencies.
backend.registerInstantiatedClass(superclass, this);
applyImpact(backend.registerInstantiatedClass(superclass,
forResolution: false));
}
ClassElement superclass = cls;
@ -356,11 +358,11 @@ class CodegenEnqueuer implements Enqueuer {
assert(invariant(element, element.isDeclaration,
message: "Element ${element} is not the declaration."));
_universe.registerStaticUse(staticUse);
backend.registerStaticUse(this, element);
applyImpact(backend.registerStaticUse(element, forResolution: false));
bool addElement = true;
switch (staticUse.kind) {
case StaticUseKind.STATIC_TEAR_OFF:
backend.registerGetOfStaticFunction(this);
applyImpact(backend.registerGetOfStaticFunction());
break;
case StaticUseKind.FIELD_GET:
case StaticUseKind.FIELD_SET:
@ -425,15 +427,17 @@ class CodegenEnqueuer implements Enqueuer {
}
void registerCallMethodWithFreeTypeVariables(Element element) {
backend.registerCallMethodWithFreeTypeVariables(element, this);
applyImpact(backend.registerCallMethodWithFreeTypeVariables(element,
forResolution: false));
}
void registerClosurizedMember(TypedElement element) {
assert(element.isInstanceMember);
if (element.type.containsTypeVariables) {
backend.registerClosureWithFreeTypeVariables(element, this);
applyImpact(backend.registerClosureWithFreeTypeVariables(element,
forResolution: false));
}
backend.registerBoundClosure(this);
applyImpact(backend.registerBoundClosure());
}
void forEach(void f(WorkItem work)) {
@ -491,7 +495,7 @@ class CodegenEnqueuer implements Enqueuer {
void registerNoSuchMethod(Element element) {
if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) {
backend.enableNoSuchMethod(this);
applyImpact(backend.enableNoSuchMethod());
enabledNoSuchMethod = true;
}
}

View file

@ -21,7 +21,7 @@ import '../dart_types.dart' show DartType;
import '../dart_types.dart' show InterfaceType;
import '../elements/elements.dart'
show ClassElement, FieldElement, LibraryElement, VariableElement;
import '../enqueue.dart';
import '../universe/use.dart' show StaticUse;
import '../universe/world_impact.dart'
show WorldImpact, StagedWorldImpactBuilder;
import 'js_backend.dart' show JavaScriptBackend;
@ -120,7 +120,10 @@ class LookupMapAnalysis {
/// entry with that key.
final _pending = <ConstantValue, List<_LookupMapInfo>>{};
final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
final StagedWorldImpactBuilder impactBuilderForResolution =
new StagedWorldImpactBuilder();
final StagedWorldImpactBuilder impactBuilderForCodegen =
new StagedWorldImpactBuilder();
/// Whether the backend is currently processing the codegen queue.
bool _inCodegen = false;
@ -129,8 +132,11 @@ class LookupMapAnalysis {
/// Compute the [WorldImpact] for the constants registered since last flush.
WorldImpact flush({bool forResolution}) {
if (forResolution) return const WorldImpact();
return impactBuilder.flush();
if (forResolution) {
return impactBuilderForResolution.flush();
} else {
return impactBuilderForCodegen.flush();
}
}
/// Whether this analysis and optimization is enabled.
@ -151,8 +157,8 @@ class LookupMapAnalysis {
reporter.reportInfo(
library, MessageKind.UNRECOGNIZED_VERSION_OF_LOOKUP_MAP);
} else {
backend.compiler.enqueuer.resolution
.addToWorkList(lookupMapVersionVariable);
impactBuilderForResolution.registerStaticUse(
new StaticUse.foreignUse(lookupMapVersionVariable));
}
}
@ -277,7 +283,8 @@ class LookupMapAnalysis {
// type_lookup_map/generic_type_test
// TODO(sigmund): can we get rid of this?
backend.computeImpactForInstantiatedConstantType(
backend.backendClasses.typeImplementation.rawType, impactBuilder);
backend.backendClasses.typeImplementation.rawType,
impactBuilderForCodegen);
_addGenerics(arg);
}
}
@ -418,7 +425,7 @@ class _LookupMapInfo {
ConstantValue constant = unusedEntries.remove(key);
usedEntries[key] = constant;
analysis.backend.computeImpactForCompileTimeConstant(
constant, analysis.impactBuilder, false);
constant, analysis.impactBuilderForCodegen, false);
}
/// Restores [original] to contain all of the entries marked as possibly used.

View file

@ -44,9 +44,13 @@ class TypeVariableHandler {
Map<TypeVariableElement, jsAst.Expression> _typeVariableConstants =
new Map<TypeVariableElement, jsAst.Expression>();
/// Impact builder used for the resolution world computation.
final StagedWorldImpactBuilder impactBuilderForResolution =
new StagedWorldImpactBuilder();
/// Impact builder used for the codegen world computation.
// TODO(johnniwinther): Add impact builder for resolution.
final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();
final StagedWorldImpactBuilder impactBuilderForCodegen =
new StagedWorldImpactBuilder();
TypeVariableHandler(this._compiler);
@ -59,16 +63,18 @@ class TypeVariableHandler {
/// Compute the [WorldImpact] for the type variables registered since last
/// flush.
WorldImpact flush({bool forResolution}) {
if (forResolution) return const WorldImpact();
return impactBuilder.flush();
if (forResolution) {
return impactBuilderForResolution.flush();
} else {
return impactBuilderForCodegen.flush();
}
}
void registerClassWithTypeVariables(ClassElement cls, Enqueuer enqueuer) {
if (enqueuer.isResolutionQueue) {
void registerClassWithTypeVariables(ClassElement cls, {bool forResolution}) {
if (forResolution) {
// On first encounter, we have to ensure that the support classes get
// resolved.
if (!_seenClassesWithTypeVariables) {
_backend.enqueueClass(enqueuer, _typeVariableClass);
_typeVariableClass.ensureResolved(_compiler.resolution);
Link constructors = _typeVariableClass.constructors;
if (constructors.isEmpty && constructors.tail.isEmpty) {
@ -76,11 +82,12 @@ class TypeVariableHandler {
"Class '$_typeVariableClass' should only have one constructor");
}
_typeVariableConstructor = _typeVariableClass.constructors.head;
_backend.enqueue(enqueuer, _typeVariableConstructor);
enqueuer.registerInstantiatedType(_typeVariableClass.rawType);
enqueuer.registerStaticUse(new StaticUse.staticInvoke(
_backend.registerBackendUse(_backend.helpers.createRuntimeType),
CallStructure.ONE_ARG));
_backend.impactTransformer.registerBackendStaticUse(
impactBuilderForResolution, _typeVariableConstructor);
_backend.impactTransformer.registerBackendInstantiation(
impactBuilderForResolution, _typeVariableClass);
_backend.impactTransformer.registerBackendStaticUse(
impactBuilderForResolution, _backend.helpers.createRuntimeType);
_seenClassesWithTypeVariables = true;
}
} else {
@ -117,7 +124,8 @@ class TypeVariableHandler {
_backend.constants.evaluate(constant);
ConstantValue value = _backend.constants.getConstantValue(constant);
_backend.computeImpactForCompileTimeConstant(value, impactBuilder, false);
_backend.computeImpactForCompileTimeConstant(
value, impactBuilderForCodegen, false);
_backend.addCompileTimeConstantForEmission(value);
constants
.add(_reifyTypeVariableConstant(value, currentTypeVariable.element));

View file

@ -36,6 +36,9 @@ class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
ResolutionWorldImpactBuilder(this.name);
@override
bool get isEmpty => false;
void registerMapLiteral(MapLiteralUse mapLiteralUse) {
assert(mapLiteralUse != null);
if (_mapLiterals == null) {

View file

@ -116,6 +116,9 @@ class DeserializedResolutionImpact extends WorldImpact
this.nativeData: const <dynamic>[]})
: this._features = features;
@override
bool get isEmpty => false;
Iterable<Feature> get features {
return _features != null
? _features.iterable(Feature.values)

View file

@ -407,10 +407,8 @@ class SsaBuilder extends ast.Visitor
bool tryInlineMethod(Element element, Selector selector, TypeMask mask,
List<HInstruction> providedArguments, ast.Node currentNode,
{InterfaceType instanceType}) {
// TODO(johnniwinther): Register this on the [registry]. Currently the
// [CodegenRegistry] calls the enqueuer, but [element] should _not_ be
// enqueued.
backend.registerStaticUse(compiler.enqueuer.codegen, element);
registry
.addImpact(backend.registerStaticUse(element, forResolution: false));
if (backend.isJsInterop(element) && !element.isFactoryConstructor) {
// We only inline factory JavaScript interop constructors.
@ -1497,23 +1495,23 @@ class SsaBuilder extends ast.Visitor
insertTraceCall(Element element) {
if (JavaScriptBackend.TRACE_METHOD == 'console') {
if (element == backend.traceHelper) return;
if (element == backend.helpers.traceHelper) return;
n(e) => e == null ? '' : e.name;
String name = "${n(element.library)}:${n(element.enclosingClass)}."
"${n(element)}";
HConstant nameConstant = addConstantString(name);
add(new HInvokeStatic(backend.traceHelper, <HInstruction>[nameConstant],
backend.dynamicType));
add(new HInvokeStatic(backend.helpers.traceHelper,
<HInstruction>[nameConstant], backend.dynamicType));
}
}
insertCoverageCall(Element element) {
if (JavaScriptBackend.TRACE_METHOD == 'post') {
if (element == backend.traceHelper) return;
if (element == backend.helpers.traceHelper) return;
// TODO(sigmund): create a better uuid for elements.
HConstant idConstant = graph.addConstantInt(element.hashCode, compiler);
HConstant nameConstant = addConstantString(element.name);
add(new HInvokeStatic(backend.traceHelper,
add(new HInvokeStatic(backend.helpers.traceHelper,
<HInstruction>[idConstant, nameConstant], backend.dynamicType));
}
}

View file

@ -33,6 +33,8 @@ class WorldImpact {
Iterable<TypeUse> get typeUses => const <TypeUse>[];
bool get isEmpty => true;
void apply(WorldImpactVisitor visitor) {
staticUses.forEach(visitor.visitStaticUse);
dynamicUses.forEach(visitor.visitDynamicUse);
@ -74,6 +76,18 @@ class WorldImpactBuilderImpl extends WorldImpact implements WorldImpactBuilder {
Set<StaticUse> _staticUses;
Set<TypeUse> _typeUses;
@override
bool get isEmpty =>
_dynamicUses == null && _staticUses == null && _typeUses == null;
/// Copy uses in [impact] to this impact builder.
void addImpact(WorldImpact impact) {
if (impact.isEmpty) return;
impact.dynamicUses.forEach(registerDynamicUse);
impact.staticUses.forEach(registerStaticUse);
impact.typeUses.forEach(registerTypeUse);
}
void registerDynamicUse(DynamicUse dynamicUse) {
assert(dynamicUse != null);
if (_dynamicUses == null) {
@ -173,6 +187,14 @@ class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
TransformedWorldImpact(this.worldImpact);
@override
bool get isEmpty {
return worldImpact.isEmpty &&
_staticUses == null &&
_typeUses == null &&
_dynamicUses == null;
}
@override
Iterable<DynamicUse> get dynamicUses {
return _dynamicUses != null ? _dynamicUses : worldImpact.dynamicUses;

View file

@ -11,7 +11,6 @@ import 'dart:io';
import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/apiimpl.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/kernel/task.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
@ -28,6 +27,7 @@ import 'package:compiler/src/platform_configuration.dart' as platform;
import 'package:compiler/src/scanner/scanner.dart';
import 'package:compiler/src/source_file_provider.dart';
import 'package:compiler/src/tokens/token.dart' show Token;
import 'package:compiler/src/universe/world_impact.dart' show WorldImpact;
import 'package:package_config/discovery.dart' show findPackages;
import 'package:package_config/packages.dart' show Packages;
import 'package:package_config/src/util.dart' show checkValidPackageUri;
@ -359,7 +359,7 @@ class MyCompiler extends CompilerImpl {
/// Performs the compilation when all libraries have been loaded.
void compileLoadedLibraries() =>
selfTask.measureSubtask("KernelCompiler.compileLoadedLibraries", () {
computeMain();
WorldImpact mainImpact = computeMain();
mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
deferredLoadTask.beforeResolution(this);
@ -369,14 +369,18 @@ class MyCompiler extends CompilerImpl {
supportSerialization: serialization.supportSerialization);
phase = Compiler.PHASE_RESOLVING;
enqueuer.resolution.applyImpact(mainImpact);
// Note: we enqueue everything in the program so we measure generating
// kernel for the entire code, not just what's reachable from main.
libraryLoader.libraries.forEach((LibraryElement library) {
fullyEnqueueLibrary(library, enqueuer.resolution);
});
backend.enqueueHelpers(enqueuer.resolution);
if (deferredLoadTask.isProgramSplit) {
enqueuer.resolution.applyImpact(
backend.computeDeferredLoadingImpact());
}
enqueuer.resolution.applyImpact(backend.computeHelpersImpact());
resolveLibraryMetadata();
reporter.log('Resolving...');
processQueue(enqueuer.resolution, mainFunction);

View file

@ -85,7 +85,7 @@ Future<CompilerImpl> reuseCompiler(
// Likewise, always be prepared for runtimeType support.
// TODO(johnniwinther): Add global switch to force RTI.
compiler.resolverWorld.hasRuntimeTypeSupport = true;
backend.registerRuntimeType(compiler.enqueuer.resolution);
compiler.enqueuer.resolution.applyImpact(backend.registerRuntimeType());
return compiler;
});
});

View file

@ -72,7 +72,8 @@ Future<String> compile(String code,
lego.Element element = compiler.mainApp.find(entry);
if (element == null) return null;
compiler.phase = Compiler.PHASE_RESOLVING;
compiler.backend.enqueueHelpers(compiler.enqueuer.resolution);
compiler.enqueuer.resolution
.applyImpact(compiler.backend.computeHelpersImpact());
compiler.processQueue(compiler.enqueuer.resolution, element);
compiler.openWorld.closeWorld(compiler.reporter);
compiler.backend.onResolutionComplete();

View file

@ -101,21 +101,21 @@ main(List<String> args) {
// enqueuing twice.
backend.typeVariableHandler = new TypeVariableHandler(compiler);
backend.enqueueHelpers(enqueuer);
if (compiler.deferredLoadTask.isProgramSplit) {
enqueuer.applyImpact(backend.computeDeferredLoadingImpact());
}
enqueuer.applyImpact(backend.computeHelpersImpact());
enqueuer.applyImpact(enqueuer.nativeEnqueuer
.processNativeClasses(compiler.libraryLoader.libraries));
enqueuer.applyImpact(
compiler.impactStrategy,
enqueuer.nativeEnqueuer
.processNativeClasses(compiler.libraryLoader.libraries));
enqueuer.applyImpact(compiler.impactStrategy,
backend.computeMainImpact(enqueuer, compiler.mainFunction));
backend.computeMainImpact(compiler.mainFunction, forResolution: true));
enqueuer.forEach((work) {
AstElement element = work.element;
ResolutionImpact resolutionImpact = build(compiler, element.resolvedAst);
WorldImpact worldImpact = compiler.backend.impactTransformer
.transformResolutionImpact(enqueuer, resolutionImpact);
enqueuer.registerProcessedElement(element);
enqueuer.applyImpact(compiler.impactStrategy, worldImpact,
impactSource: element);
enqueuer.applyImpact(worldImpact, impactSource: element);
});
ClosedWorld closedWorld =
enqueuer.universe.openWorld.closeWorld(compiler.reporter);

View file

@ -16,6 +16,8 @@ import 'package:compiler/src/resolution/registry.dart';
import 'package:compiler/src/resolution/resolution_result.dart';
import 'package:compiler/src/resolution/scope.dart';
import 'package:compiler/src/resolution/tree_elements.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'compiler_helper.dart';
import 'link_helper.dart';
@ -241,7 +243,8 @@ Future testSwitch() {
compiler.resolveStatement("Foo foo;");
ClassElement fooElement = compiler.mainApp.find("Foo");
FunctionElement funElement = fooElement.lookupLocalMember("foo");
compiler.enqueuer.resolution.addToWorkList(funElement);
compiler.enqueuer.resolution.applyImpact(new WorldImpactBuilderImpl()
..registerStaticUse(new StaticUse.foreignUse(funElement)));
compiler.processQueue(compiler.enqueuer.resolution, null);
DiagnosticCollector collector = compiler.diagnosticCollector;
Expect.equals(0, collector.warnings.length);

View file

@ -8,6 +8,8 @@ import 'package:compiler/src/js_backend/backend_helpers.dart';
import 'package:compiler/src/js_backend/js_backend.dart';
import 'package:compiler/src/types/types.dart';
import 'package:compiler/src/world.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'compiler_helper.dart';
import 'type_mask_test_helper.dart';
@ -737,21 +739,24 @@ void main() {
JavaScriptBackend backend = compiler.backend;
BackendHelpers helpers = backend.helpers;
ClosedWorld world = compiler.openWorld.closeWorld(compiler.reporter);
WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
helpers.interceptorsLibrary.forEachLocalMember((element) {
if (element.isClass) {
element.ensureResolved(compiler.resolution);
compiler.enqueuer.resolution.registerInstantiatedType(element.rawType);
impactBuilder
.registerTypeUse(new TypeUse.instantiation(element.rawType));
}
});
ClassElement patternImplClass = compiler.mainApp.find('PatternImpl');
patternImplClass.ensureResolved(compiler.resolution);
compiler.enqueuer.resolution
.registerInstantiatedType(compiler.coreTypes.mapType());
compiler.enqueuer.resolution
.registerInstantiatedType(compiler.coreTypes.functionType);
compiler.enqueuer.resolution
.registerInstantiatedType(patternImplClass.rawType);
impactBuilder.registerTypeUse(
new TypeUse.instantiation(compiler.coreTypes.mapType()));
impactBuilder.registerTypeUse(
new TypeUse.instantiation(compiler.coreTypes.functionType));
impactBuilder
.registerTypeUse(new TypeUse.instantiation(patternImplClass.rawType));
compiler.enqueuer.resolution.applyImpact(impactBuilder);
compiler.openWorld.closeWorld(compiler.reporter);
// Grab hold of a supertype for String so we can produce potential