| Index: pkg/compiler/lib/src/js_backend/backend.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
|
| index 03e5839570856295873893783f61988c4c98356e..1bf2a94052410488772eb7cb416f29b7631d7a82 100644
|
| --- a/pkg/compiler/lib/src/js_backend/backend.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/backend.dart
|
| @@ -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,39 @@ 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) {
|
| + WorldImpact _registerComputeSignature() {
|
| // 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);
|
| + 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 +1385,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 +1427,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 +1443,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 +1482,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 +1543,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 +1765,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 +1804,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 +1822,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 +2259,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 +2272,7 @@ class JavaScriptBackend extends Backend {
|
| if (!enabledNoSuchMethod &&
|
| (noSuchMethodRegistry.hasThrowingNoSuchMethod ||
|
| noSuchMethodRegistry.hasComplexNoSuchMethod)) {
|
| - enableNoSuchMethod(enqueuer);
|
| + enqueuer.applyImpact(enableNoSuchMethod());
|
| enabledNoSuchMethod = true;
|
| }
|
|
|
| @@ -2369,10 +2282,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 +2294,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 +2341,7 @@ class JavaScriptBackend extends Backend {
|
| }
|
| metadataConstants.clear();
|
| }
|
| - enqueuer.applyImpact(compiler.impactStrategy, impactBuilder.flush());
|
| + enqueuer.applyImpact(impactBuilder.flush());
|
| }
|
| return true;
|
| }
|
| @@ -2579,7 +2490,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 +2502,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 +2524,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 +2919,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 +2967,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);
|
|
|