Index: pkg/compiler/lib/src/js_backend/impact_transformer.dart |
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart |
index 998b9d4b90a6cd857634de36e325e0bf291fc039..e3ab59eddf601b190d9a0558bd3abcec92713338 100644 |
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart |
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart |
@@ -5,121 +5,146 @@ |
library js_backend.backend.impact_transformer; |
import '../common.dart'; |
+import '../common_elements.dart'; |
import '../common/backend_api.dart' show ImpactTransformer; |
import '../common/codegen.dart' show CodegenImpact; |
-import '../common/resolution.dart' show ResolutionImpact; |
+import '../common/resolution.dart' show Resolution, ResolutionImpact; |
import '../constants/expressions.dart'; |
import '../constants/values.dart'; |
import '../common_elements.dart' show ElementEnvironment; |
import '../elements/elements.dart'; |
import '../elements/resolution_types.dart'; |
import '../enqueue.dart' show ResolutionEnqueuer; |
+import '../native/enqueue.dart'; |
import '../native/native.dart' as native; |
+import '../options.dart'; |
import '../universe/feature.dart'; |
import '../universe/use.dart' |
show StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact; |
import '../util/util.dart'; |
import 'backend.dart'; |
+import 'backend_helpers.dart'; |
import 'backend_impact.dart'; |
import 'backend_usage.dart'; |
import 'checked_mode_helpers.dart'; |
+import 'custom_elements_analysis.dart'; |
+import 'interceptor_data.dart'; |
+import 'lookup_map_analysis.dart'; |
+import 'mirrors_data.dart'; |
+import 'namer.dart'; |
+import 'native_data.dart'; |
class JavaScriptImpactTransformer extends ImpactTransformer { |
- final JavaScriptBackend backend; |
- |
- JavaScriptImpactTransformer(this.backend); |
- |
- BackendImpacts get impacts => backend.impacts; |
- |
- ElementEnvironment get elementEnvironment => |
- backend.compiler.elementEnvironment; |
+ final CompilerOptions _options; |
+ final Resolution _resolution; |
+ final ElementEnvironment _elementEnvironment; |
+ final CommonElements _commonElements; |
+ final BackendImpacts _impacts; |
+ final NativeClassData _nativeClassData; |
+ final NativeResolutionEnqueuer _nativeResolutionEnqueuer; |
+ final BackendUsageBuilder _backendUsageBuider; |
+ final MirrorsData _mirrorsData; |
+ final CustomElementsResolutionAnalysis _customElementsResolutionAnalysis; |
+ final RuntimeTypesNeedBuilder _rtiNeedBuilder; |
+ |
+ JavaScriptImpactTransformer( |
+ this._options, |
+ this._resolution, |
+ this._elementEnvironment, |
+ this._commonElements, |
+ this._impacts, |
+ this._nativeClassData, |
+ this._nativeResolutionEnqueuer, |
+ this._backendUsageBuider, |
+ this._mirrorsData, |
+ this._customElementsResolutionAnalysis, |
+ this._rtiNeedBuilder); |
@override |
WorldImpact transformResolutionImpact( |
ResolutionEnqueuer enqueuer, ResolutionImpact worldImpact) { |
- BackendUsageBuilder backendUsage = backend.backendUsageBuilder; |
TransformedWorldImpact transformed = |
new TransformedWorldImpact(worldImpact); |
void registerImpact(BackendImpact impact) { |
- impact.registerImpact(transformed, elementEnvironment); |
- backendUsage.processBackendImpact(impact); |
+ impact.registerImpact(transformed, _elementEnvironment); |
+ _backendUsageBuider.processBackendImpact(impact); |
} |
for (Feature feature in worldImpact.features) { |
switch (feature) { |
case Feature.ABSTRACT_CLASS_INSTANTIATION: |
- registerImpact(impacts.abstractClassInstantiation); |
+ registerImpact(_impacts.abstractClassInstantiation); |
break; |
case Feature.ASSERT: |
- registerImpact(impacts.assertWithoutMessage); |
+ registerImpact(_impacts.assertWithoutMessage); |
break; |
case Feature.ASSERT_WITH_MESSAGE: |
- registerImpact(impacts.assertWithMessage); |
+ registerImpact(_impacts.assertWithMessage); |
break; |
case Feature.ASYNC: |
- registerImpact(impacts.asyncBody); |
+ registerImpact(_impacts.asyncBody); |
break; |
case Feature.ASYNC_FOR_IN: |
- registerImpact(impacts.asyncForIn); |
+ registerImpact(_impacts.asyncForIn); |
break; |
case Feature.ASYNC_STAR: |
- registerImpact(impacts.asyncStarBody); |
+ registerImpact(_impacts.asyncStarBody); |
break; |
case Feature.CATCH_STATEMENT: |
- registerImpact(impacts.catchStatement); |
+ registerImpact(_impacts.catchStatement); |
break; |
case Feature.COMPILE_TIME_ERROR: |
- if (backend.compiler.options.generateCodeWithCompileTimeErrors) { |
+ if (_options.generateCodeWithCompileTimeErrors) { |
// TODO(johnniwinther): This should have its own uncatchable error. |
- registerImpact(impacts.throwRuntimeError); |
+ registerImpact(_impacts.throwRuntimeError); |
} |
break; |
case Feature.FALL_THROUGH_ERROR: |
- registerImpact(impacts.fallThroughError); |
+ registerImpact(_impacts.fallThroughError); |
break; |
case Feature.FIELD_WITHOUT_INITIALIZER: |
case Feature.LOCAL_WITHOUT_INITIALIZER: |
transformed.registerTypeUse( |
- new TypeUse.instantiation(backend.commonElements.nullType)); |
- registerImpact(impacts.nullLiteral); |
+ new TypeUse.instantiation(_commonElements.nullType)); |
+ registerImpact(_impacts.nullLiteral); |
break; |
case Feature.LAZY_FIELD: |
- registerImpact(impacts.lazyField); |
+ registerImpact(_impacts.lazyField); |
break; |
case Feature.STACK_TRACE_IN_CATCH: |
- registerImpact(impacts.stackTraceInCatch); |
+ registerImpact(_impacts.stackTraceInCatch); |
break; |
case Feature.STRING_INTERPOLATION: |
- registerImpact(impacts.stringInterpolation); |
+ registerImpact(_impacts.stringInterpolation); |
break; |
case Feature.STRING_JUXTAPOSITION: |
- registerImpact(impacts.stringJuxtaposition); |
+ registerImpact(_impacts.stringJuxtaposition); |
break; |
case Feature.SUPER_NO_SUCH_METHOD: |
- registerImpact(impacts.superNoSuchMethod); |
+ registerImpact(_impacts.superNoSuchMethod); |
break; |
case Feature.SYMBOL_CONSTRUCTOR: |
- registerImpact(impacts.symbolConstructor); |
+ registerImpact(_impacts.symbolConstructor); |
break; |
case Feature.SYNC_FOR_IN: |
- registerImpact(impacts.syncForIn); |
+ registerImpact(_impacts.syncForIn); |
break; |
case Feature.SYNC_STAR: |
- registerImpact(impacts.syncStarBody); |
+ registerImpact(_impacts.syncStarBody); |
break; |
case Feature.THROW_EXPRESSION: |
- registerImpact(impacts.throwExpression); |
+ registerImpact(_impacts.throwExpression); |
break; |
case Feature.THROW_NO_SUCH_METHOD: |
- registerImpact(impacts.throwNoSuchMethod); |
+ registerImpact(_impacts.throwNoSuchMethod); |
break; |
case Feature.THROW_RUNTIME_ERROR: |
- registerImpact(impacts.throwRuntimeError); |
+ registerImpact(_impacts.throwRuntimeError); |
break; |
case Feature.TYPE_VARIABLE_BOUNDS_CHECK: |
- registerImpact(impacts.typeVariableBoundCheck); |
+ registerImpact(_impacts.typeVariableBoundCheck); |
break; |
} |
} |
@@ -142,7 +167,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
hasAsCast = true; |
break; |
case TypeUseKind.CHECKED_MODE_CHECK: |
- if (backend.compiler.options.enableTypeAssertions) { |
+ if (_options.enableTypeAssertions) { |
onIsCheck(type, transformed); |
} |
break; |
@@ -150,7 +175,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
onIsCheck(type, transformed); |
break; |
case TypeUseKind.TYPE_LITERAL: |
- backend.customElementsResolutionAnalysis.registerTypeLiteral(type); |
+ _customElementsResolutionAnalysis.registerTypeLiteral(type); |
if (type.isTypeVariable && type is! MethodTypeVariableType) { |
// GENERIC_METHODS: The `is!` test above filters away method type |
// variables, because they have the value `dynamic` with the |
@@ -158,9 +183,8 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
// '--generic-method-syntax'. This must be revised in order to |
// support generic methods fully. |
ClassElement cls = type.element.enclosingClass; |
- backend.rtiNeedBuilder |
- .registerClassUsingTypeVariableExpression(cls); |
- registerImpact(impacts.typeVariableExpression); |
+ _rtiNeedBuilder.registerClassUsingTypeVariableExpression(cls); |
+ registerImpact(_impacts.typeVariableExpression); |
} |
hasTypeLiteral = true; |
break; |
@@ -168,20 +192,20 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
if (hasAsCast) { |
- registerImpact(impacts.asCheck); |
+ registerImpact(_impacts.asCheck); |
} |
if (hasTypeLiteral) { |
- transformed.registerTypeUse( |
- new TypeUse.instantiation(backend.compiler.commonElements.typeType)); |
- registerImpact(impacts.typeLiteral); |
+ transformed |
+ .registerTypeUse(new TypeUse.instantiation(_commonElements.typeType)); |
+ registerImpact(_impacts.typeLiteral); |
} |
for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) { |
// TODO(johnniwinther): Use the [isEmpty] property when factory |
// constructors are registered directly. |
if (mapLiteralUse.isConstant) { |
- registerImpact(impacts.constantMapLiteral); |
+ registerImpact(_impacts.constantMapLiteral); |
} else { |
transformed |
.registerTypeUse(new TypeUse.instantiation(mapLiteralUse.type)); |
@@ -200,19 +224,19 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
if (worldImpact.constSymbolNames.isNotEmpty) { |
- registerImpact(impacts.constSymbol); |
+ registerImpact(_impacts.constSymbol); |
for (String constSymbolName in worldImpact.constSymbolNames) { |
- backend.mirrorsData.registerConstSymbol(constSymbolName); |
+ _mirrorsData.registerConstSymbol(constSymbolName); |
} |
} |
for (StaticUse staticUse in worldImpact.staticUses) { |
switch (staticUse.kind) { |
case StaticUseKind.CLOSURE: |
- registerImpact(impacts.closure); |
+ registerImpact(_impacts.closure); |
LocalFunctionElement closure = staticUse.element; |
if (closure.type.containsTypeVariables) { |
- registerImpact(impacts.computeSignature); |
+ registerImpact(_impacts.computeSignature); |
} |
break; |
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
@@ -226,19 +250,19 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
for (ConstantExpression constant in worldImpact.constantLiterals) { |
switch (constant.kind) { |
case ConstantExpressionKind.NULL: |
- registerImpact(impacts.nullLiteral); |
+ registerImpact(_impacts.nullLiteral); |
break; |
case ConstantExpressionKind.BOOL: |
- registerImpact(impacts.boolLiteral); |
+ registerImpact(_impacts.boolLiteral); |
break; |
case ConstantExpressionKind.INT: |
- registerImpact(impacts.intLiteral); |
+ registerImpact(_impacts.intLiteral); |
break; |
case ConstantExpressionKind.DOUBLE: |
- registerImpact(impacts.doubleLiteral); |
+ registerImpact(_impacts.doubleLiteral); |
break; |
case ConstantExpressionKind.STRING: |
- registerImpact(impacts.stringLiteral); |
+ registerImpact(_impacts.stringLiteral); |
break; |
default: |
assert(invariant(NO_LOCATION_SPANNABLE, false, |
@@ -247,8 +271,8 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
for (native.NativeBehavior behavior in worldImpact.nativeData) { |
- backend.nativeResolutionEnqueuer |
- .registerNativeBehavior(transformed, behavior, worldImpact); |
+ _nativeResolutionEnqueuer.registerNativeBehavior( |
+ transformed, behavior, worldImpact); |
} |
return transformed; |
@@ -264,59 +288,92 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
// then the class of the type variable does too. |
ClassElement contextClass = Types.getClassContext(type); |
if (contextClass != null) { |
- backend.rtiNeedBuilder.registerRtiDependency(type.element, contextClass); |
+ _rtiNeedBuilder.registerRtiDependency(type.element, contextClass); |
} |
} |
// TODO(johnniwinther): Maybe split this into [onAssertType] and [onTestType]. |
void onIsCheck(ResolutionDartType type, TransformedWorldImpact transformed) { |
- BackendUsageBuilder backendUsage = backend.backendUsageBuilder; |
- |
void registerImpact(BackendImpact impact) { |
- impact.registerImpact(transformed, elementEnvironment); |
- backendUsage.processBackendImpact(impact); |
+ impact.registerImpact(transformed, _elementEnvironment); |
+ _backendUsageBuider.processBackendImpact(impact); |
} |
registerRequiredType(type); |
- type.computeUnaliased(backend.resolution); |
+ type.computeUnaliased(_resolution); |
type = type.unaliased; |
- registerImpact(impacts.typeCheck); |
+ registerImpact(_impacts.typeCheck); |
- bool inCheckedMode = backend.compiler.options.enableTypeAssertions; |
+ bool inCheckedMode = _options.enableTypeAssertions; |
if (inCheckedMode) { |
- registerImpact(impacts.checkedModeTypeCheck); |
+ registerImpact(_impacts.checkedModeTypeCheck); |
} |
if (type.isMalformed) { |
- registerImpact(impacts.malformedTypeCheck); |
+ registerImpact(_impacts.malformedTypeCheck); |
} |
if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) { |
- registerImpact(impacts.genericTypeCheck); |
+ registerImpact(_impacts.genericTypeCheck); |
if (inCheckedMode) { |
- registerImpact(impacts.genericCheckedModeTypeCheck); |
+ registerImpact(_impacts.genericCheckedModeTypeCheck); |
} |
if (type.isTypeVariable) { |
- registerImpact(impacts.typeVariableTypeCheck); |
+ registerImpact(_impacts.typeVariableTypeCheck); |
if (inCheckedMode) { |
- registerImpact(impacts.typeVariableCheckedModeTypeCheck); |
+ registerImpact(_impacts.typeVariableCheckedModeTypeCheck); |
} |
} |
} |
if (type is ResolutionFunctionType) { |
- registerImpact(impacts.functionTypeCheck); |
+ registerImpact(_impacts.functionTypeCheck); |
} |
if (type is ResolutionInterfaceType && |
- backend.nativeClassData.isNativeClass(type.element)) { |
- registerImpact(impacts.nativeTypeCheck); |
+ _nativeClassData.isNativeClass(type.element)) { |
+ registerImpact(_impacts.nativeTypeCheck); |
} |
} |
+} |
+ |
+class CodegenImpactTransformer { |
+ // TODO(johnniwinther): Remove the need for this. |
+ final JavaScriptBackend _backend; |
+ |
+ final CompilerOptions _options; |
+ final ElementEnvironment _elementEnvironment; |
+ final BackendHelpers _helpers; |
+ final BackendImpacts _impacts; |
+ final CheckedModeHelpers _checkedModeHelpers; |
+ final NativeData _nativeData; |
+ final RuntimeTypesNeed _rtiNeed; |
+ final NativeCodegenEnqueuer _nativeCodegenEnqueuer; |
+ final Namer _namer; |
+ final MirrorsData _mirrorsData; |
+ final OneShotInterceptorData _oneShotInterceptorData; |
+ final LookupMapAnalysis _lookupMapAnalysis; |
+ final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis; |
+ |
+ CodegenImpactTransformer( |
+ this._backend, |
+ this._options, |
+ this._elementEnvironment, |
+ this._helpers, |
+ this._impacts, |
+ this._checkedModeHelpers, |
+ this._nativeData, |
+ this._rtiNeed, |
+ this._nativeCodegenEnqueuer, |
+ this._namer, |
+ this._mirrorsData, |
+ this._oneShotInterceptorData, |
+ this._lookupMapAnalysis, |
+ this._customElementsCodegenAnalysis); |
void onIsCheckForCodegen( |
ResolutionDartType type, TransformedWorldImpact transformed) { |
if (type.isDynamic) return; |
type = type.unaliased; |
- impacts.typeCheck.registerImpact(transformed, elementEnvironment); |
+ _impacts.typeCheck.registerImpact(transformed, _elementEnvironment); |
- bool inCheckedMode = backend.compiler.options.enableTypeAssertions; |
+ bool inCheckedMode = _options.enableTypeAssertions; |
// [registerIsCheck] is also called for checked mode checks, so we |
// need to register checked mode helpers. |
if (inCheckedMode) { |
@@ -324,29 +381,29 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
// calls to [enqueue] with the resolution enqueuer serve as assertions |
// that the helper was in fact added. |
// TODO(13155): Find a way to enqueue helpers lazily. |
- CheckedModeHelper helper = backend.checkedModeHelpers |
- .getCheckedModeHelper(type, typeCast: false); |
+ CheckedModeHelper helper = |
+ _checkedModeHelpers.getCheckedModeHelper(type, typeCast: false); |
if (helper != null) { |
- StaticUse staticUse = helper.getStaticUse(backend.helpers); |
+ StaticUse staticUse = helper.getStaticUse(_helpers); |
transformed.registerStaticUse(staticUse); |
} |
// We also need the native variant of the check (for DOM types). |
- helper = backend.checkedModeHelpers |
- .getNativeCheckedModeHelper(type, typeCast: false); |
+ helper = |
+ _checkedModeHelpers.getNativeCheckedModeHelper(type, typeCast: false); |
if (helper != null) { |
- StaticUse staticUse = helper.getStaticUse(backend.helpers); |
+ StaticUse staticUse = helper.getStaticUse(_helpers); |
transformed.registerStaticUse(staticUse); |
} |
} |
if (!type.treatAsRaw || type.containsTypeVariables) { |
- impacts.genericIsCheck.registerImpact(transformed, elementEnvironment); |
+ _impacts.genericIsCheck.registerImpact(transformed, _elementEnvironment); |
} |
if (type is ResolutionInterfaceType && |
- backend.nativeData.isNativeClass(type.element)) { |
+ _nativeData.isNativeClass(type.element)) { |
// We will neeed to add the "$is" and "$as" properties on the |
// JavaScript object prototype, so we make sure |
// [:defineProperty:] is compiled. |
- impacts.nativeTypeCheck.registerImpact(transformed, elementEnvironment); |
+ _impacts.nativeTypeCheck.registerImpact(transformed, _elementEnvironment); |
} |
} |
@@ -358,7 +415,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
ResolutionDartType type = typeUse.type; |
switch (typeUse.kind) { |
case TypeUseKind.INSTANTIATION: |
- backend.lookupMapAnalysis.registerInstantiatedType(type); |
+ _lookupMapAnalysis.registerInstantiatedType(type); |
break; |
case TypeUseKind.IS_CHECK: |
onIsCheckForCodegen(type, transformed); |
@@ -368,63 +425,66 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
for (ConstantValue constant in impact.compileTimeConstants) { |
- backend.computeImpactForCompileTimeConstant(constant, transformed, |
+ _backend.computeImpactForCompileTimeConstant(constant, transformed, |
forResolution: false); |
- backend.addCompileTimeConstantForEmission(constant); |
+ _backend.addCompileTimeConstantForEmission(constant); |
} |
for (Pair<ResolutionDartType, ResolutionDartType> check |
in impact.typeVariableBoundsSubtypeChecks) { |
- backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
+ _backend.registerTypeVariableBoundsSubtypeCheck(check.a, check.b); |
} |
for (StaticUse staticUse in impact.staticUses) { |
switch (staticUse.kind) { |
case StaticUseKind.CLOSURE: |
LocalFunctionElement closure = staticUse.element; |
- if (backend.rtiNeed.localFunctionNeedsRti(closure)) { |
- impacts.computeSignature |
- .registerImpact(transformed, elementEnvironment); |
+ if (_rtiNeed.localFunctionNeedsRti(closure)) { |
+ _impacts.computeSignature |
+ .registerImpact(transformed, _elementEnvironment); |
} |
break; |
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
case StaticUseKind.CONSTRUCTOR_INVOKE: |
- backend.lookupMapAnalysis.registerInstantiatedType(staticUse.type); |
+ _lookupMapAnalysis.registerInstantiatedType(staticUse.type); |
break; |
default: |
} |
} |
for (String name in impact.constSymbols) { |
- backend.mirrorsData.registerConstSymbol(name); |
+ _mirrorsData.registerConstSymbol(name); |
} |
for (Set<ClassElement> classes in impact.specializedGetInterceptors) { |
- backend.oneShotInterceptorData |
- .registerSpecializedGetInterceptor(classes, backend.namer); |
+ _oneShotInterceptorData.registerSpecializedGetInterceptor( |
+ classes, _namer); |
} |
if (impact.usesInterceptor) { |
- if (backend.nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { |
- impacts.interceptorUse.registerImpact(transformed, elementEnvironment); |
+ if (_nativeCodegenEnqueuer.hasInstantiatedNativeClasses) { |
+ _impacts.interceptorUse |
+ .registerImpact(transformed, _elementEnvironment); |
} |
} |
for (ClassElement element in impact.typeConstants) { |
- backend.customElementsCodegenAnalysis.registerTypeConstant(element); |
- backend.lookupMapAnalysis.registerTypeConstant(element); |
+ _customElementsCodegenAnalysis.registerTypeConstant(element); |
+ _lookupMapAnalysis.registerTypeConstant(element); |
} |
for (FunctionElement element in impact.asyncMarkers) { |
switch (element.asyncMarker) { |
case AsyncMarker.ASYNC: |
- impacts.asyncBody.registerImpact(transformed, elementEnvironment); |
+ _impacts.asyncBody.registerImpact(transformed, _elementEnvironment); |
break; |
case AsyncMarker.SYNC_STAR: |
- impacts.syncStarBody.registerImpact(transformed, elementEnvironment); |
+ _impacts.syncStarBody |
+ .registerImpact(transformed, _elementEnvironment); |
break; |
case AsyncMarker.ASYNC_STAR: |
- impacts.asyncStarBody.registerImpact(transformed, elementEnvironment); |
+ _impacts.asyncStarBody |
+ .registerImpact(transformed, _elementEnvironment); |
break; |
} |
} |