mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:29:48 +00:00
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:
parent
bf13fc1b28
commit
c102d3f72a
|
@ -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].
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -843,8 +843,8 @@ class DeferredLoadTask extends CompilerTask {
|
|||
});
|
||||
}
|
||||
if (isProgramSplit) {
|
||||
isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported(
|
||||
compiler.enqueuer.resolution, lastDeferred);
|
||||
isProgramSplit =
|
||||
compiler.backend.enableDeferredLoadingIfSupported(lastDeferred);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue